Compare commits

..

93 Commits

Author SHA1 Message Date
Andrew Welker
22453d4786 Merge pull request #319 from PepperDash/release/1.5.7
Release 1.5.7
2020-07-10 08:25:29 -07:00
Andrew Welker
8341631618 Merge branch 'main' into release/1.5.7 2020-07-09 15:04:07 -07:00
Andrew Welker
6a4c7bb65e Merge pull request #317 from PepperDash/hotfix/refactor-dm-bridging
Refactor DM Chassis Bridging
2020-07-09 14:56:09 -07:00
Andrew Welker
276c681b66 Merge branch 'main' into hotfix/refactor-dm-bridging 2020-07-09 14:29:36 -06:00
Andrew Welker
414a4a9564 Remove Check for HdcpSupportedLevel 2020-07-09 14:23:13 -06:00
Andrew Welker
25cb4e8727 change to HdcpSupportedLevelFeedback and...
...added debug statement
2020-07-09 11:24:36 -06:00
Andrew Welker
aff2371a4b Merge pull request #315 from PepperDash/hotfix/dmtx4kz100c-fix
Change base class for DM-TX-4KZ-100-C-1G
2020-07-08 16:28:00 -07:00
Andrew Welker
7a93223678 Change base class for DM-TX-4KZ-100-C-1G 2020-07-08 14:24:45 -06:00
Andrew Welker
5590925774 fix HDCP state feedback to link to endpoint 2020-07-08 13:43:06 -06:00
Andrew Welker
3b73a7d73c Update DM Transmitters to expose...
HDCP State feedback on the base class
2020-07-08 13:42:35 -06:00
Andrew Welker
2f7e6bf778 Merge pull request #307 from PepperDash/hotfix/bridge-registration
Update EISC Registration to happen AFTER devices are linked
2020-07-08 11:32:15 -07:00
Andrew Welker
98d3d8182e Update LinkToApi to correctly link HDCP settings 2020-07-08 12:15:50 -06:00
Andrew Welker
0da38f5fd2 figuring it out... 2020-07-08 12:15:50 -06:00
Andrew Welker
bd4ae16ab7 add some error handling for missing config values 2020-07-08 12:15:50 -06:00
Andrew Welker
1d2722d409 closes #285 refactor LinkToApi method 2020-07-08 12:15:50 -06:00
Andrew Welker
38d6200409 Log error and notices when necessary 2020-07-08 12:06:40 -06:00
Andrew Welker
e8d42b701e Updated logging to write to ErrorLog as well 2020-07-08 12:00:18 -06:00
Andrew Welker
0686e9d054 Merge branch 'main' into hotfix/bridge-registration 2020-07-08 11:59:21 -06:00
Andrew Welker
b917cb552e Merge pull request #310 from PepperDash/hotfix/program-initialization
Update ControlSystem to control program startup for subsequent programs better
2020-07-08 10:54:51 -07:00
Andrew Welker
a1ee157ab8 add debug statement for catching EISC registration result. 2020-07-08 11:47:36 -06:00
Andrew Welker
b1befeb32d Add program init complete logic 2020-07-08 11:38:09 -06:00
Andrew Welker
615c0d1545 move EISC registration 2020-07-07 13:25:26 -06:00
Neil Dorin
a2e041652d Merge pull request #304 from PepperDash/feature/minor-updates
Add bulk device add method and update Eisc
2020-07-06 15:50:30 -06:00
Andrew Welker
76033f53fc Changes Debug statement level 2020-07-06 13:48:52 -06:00
Andrew Welker
fa4d4bbd0f add AddDevice method for bulk adding devices 2020-07-06 13:38:36 -06:00
Andrew Welker
08a0cdfddd update debug statements to be level 2 2020-07-06 13:38:36 -06:00
Andrew Welker
56e4488087 Merge pull request #284 from PepperDash/hotfix/GenericRelay-ctor-issues
Fix GenericRelayDevice Constructor
2020-07-06 13:36:43 -06:00
Neil Dorin
62b57e453d Merge branch 'development' into hotfix/GenericRelay-ctor-issues 2020-07-06 12:07:00 -06:00
Neil Dorin
2a1ff2e32b Merge pull request #283 from PepperDash/hotfix/GenericRelay-ctor-issues
Fix GenericRelayDevice Constructor
2020-07-06 12:06:40 -06:00
Andrew Welker
8ede3a49ae Merge pull request #303 from PepperDash/feature/Add-DinCenCn2
Add support for the DIN-CEN-CN
2020-07-06 09:55:33 -06:00
Trevor Payne
ca75b751a7 Update GlsOccupancyController to use IHasCresnetBranches Interface
Resolves #297
2020-07-02 15:42:14 -05:00
Trevor Payne
7ed4f479a9 Update GlsOccupancyBaseController to use IHasCresnetBranches Interface
InProgress #297
2020-07-02 15:40:11 -05:00
Trevor Payne
3eeca2fbed Update GlsPartitionSensorController to use IHasCresnetBranches Interface
InProgress #297
2020-07-02 15:38:56 -05:00
Trevor Payne
82fb724bdd Update StatusSignController to use IHasCresnetBranches Interface
InProgress #297
2020-07-02 15:37:56 -05:00
Trevor Payne
4360dcdca9 Update C2nRthsController to use IHasCresnetBranches Interface
Inprogress #297
2020-07-02 15:36:59 -05:00
Trevor Payne
bfe87ae090 Added new interface IHasCresnetBranches
Added new CinCenCn2Controller

InProgress #297
2020-07-02 15:35:09 -05:00
Trevor Payne
8497924c85 Merge pull request #299 from PepperDash/feature/Move-OccupancySensors
Move Occupancy Sensors into PepperDash.Essentials.Core
2020-07-02 14:57:40 -05:00
Trevor Payne
52bfbb6dcf Fixed all Merging Conflicts 2020-07-02 13:41:51 -05:00
Trevor Payne
715a8af0a3 Merge Conficts 2020-07-02 13:37:05 -05:00
Andrew Welker
86acda9935 Merge pull request #302 from PepperDash/bugfix/Fix-HdMd4x1-controller
Bugfix/fix hd md4x1 controller
2020-07-02 11:42:49 -06:00
Trevor Payne
12a9146d79 Merge branch 'development' into bugfix/Fix-HdMd4x1-controller 2020-07-02 12:21:45 -05:00
Trevor Payne
4ee9e2aa26 Merge branch 'bugfix/Fix-HdMd4x1-controller' of https://github.com/PepperDash/Essentials into bugfix/Fix-HdMd4x1-controller 2020-07-02 12:10:07 -05:00
Trevor Payne
b65ecddb39 Change base class on HdMdNxM4kEController to be CrestronGenericBaseDevice
Add required Factory class to HdMdNxM4kEController

Fixes #280
2020-07-02 12:08:54 -05:00
Andrew Welker
1c8b44e3d7 Merge pull request #291 from PepperDash/feature/CloudConnected-CiscoSpark
Added a null check to determining SIP information
2020-07-02 10:56:38 -06:00
Andrew Welker
bc94560536 Merge branch 'development' into feature/CloudConnected-CiscoSpark 2020-07-02 10:39:20 -06:00
Andrew Welker
ae424a2a10 Merge pull request #296 from PepperDash/feature/Cresnet-Enhancements
Update Cresnet device classes
2020-07-02 10:38:01 -06:00
Andrew Welker
5b679c1f35 Merge branch 'development' into feature/Cresnet-Enhancements 2020-07-01 19:05:09 -06:00
Andrew Welker
88c4c4ae77 Merge pull request #295 from PepperDash/feature/Add-Dmc4kzHdo
Adds Dmc4kzHdo
2020-07-01 19:03:01 -06:00
Trevor Payne
e705d2191a Moved Occupancy Sensors into PepperDash.Essentials.Core
Resolves #298
2020-07-01 19:30:45 -05:00
Trevor Payne
6a3d11dee1 Added missing RegisterCrestronGenericBase() call into GlsPartitionSensorController
resolves #292
2020-07-01 17:10:47 -05:00
Trevor Payne
0d802bdeed Fixed issues with Debug calls in PreActivation Actions for Cresnet Devices
Fixed issues related to subscribing to GlsOccupancySensorBase Events

Resolves #292
2020-07-01 16:57:42 -05:00
Trevor Payne
00958164ff Move GlsPartitionSensorController into PepperDash.Essentials.Core
Add GlsPartitionSensorControllerFactory to GlsPartitionSensorController

Updates GlsPartitionSensorController to register device in PreActivate

Resolves #292
2020-07-01 16:16:41 -05:00
Trevor Payne
2fea151089 Changes to CrestronGenericBase
Refactor RfGatewayController

new IHasReady interface

Updates to Hrxx0WirelessRemoteController

merge in development

Addresses #292
2020-07-01 16:03:32 -05:00
Trevor Payne
bfa49b4772 Merge branch 'development' into feature/Cresnet-Enhancements 2020-07-01 15:53:26 -05:00
Trevor Payne
9596d0f3c3 Adds Dmc4kzHdo
Resolves #294
2020-07-01 10:44:28 -05:00
Trevor Payne
0a3f2bb524 WIP Cresnet Gateway SUpport 2020-07-01 10:35:57 -05:00
Andrew Welker
38ae5dcd2f Merge pull request #289 from PepperDash/feature/glspartcn-partition-sensor
Add support for GLS-PART-CN Partition Sensor
2020-06-30 17:20:36 -06:00
Jason DeVito
ea86c8b639 Removed funcs and updated feedbacks in constructor 2020-06-30 17:32:50 -05:00
Trevor Payne
ac379763ce Updates to Cresnet OccSensor Classes
Addresses #292
2020-06-30 15:25:20 -05:00
Trevor Payne
b694f7640a Minor Fixes to CrestronGenericBaseDevice
Update StatusSignController constructor and factory to build device in PreActivation phase

Addresses #292
2020-06-30 15:05:42 -05:00
Trevor Payne
f954043981 Updated C2NRthsController Class to build new devices in PreActivate Method
Addresses #292
2020-06-30 14:48:31 -05:00
Trevor Payne
495bf70d3a Changes to CrestronGenericBridgeableBaseDevice and CrestronGenericBaseDevice to allow it to take a func<DeviceConfig, GenericBase> in an overloaded constructor
Addresses #292
2020-06-30 14:46:46 -05:00
Jason DeVito
e1c93cc13a Updates to correct 'hardware' references accidentally changed to 'sensor'. Updated SIMPLBridge example config to include GLS-PART-CN configuration
Resolves #270
2020-06-30 12:03:48 -05:00
Trevor Payne
ce9c8042e4 Merge branch 'development' into feature/CloudConnected-CiscoSpark 2020-06-30 11:07:18 -05:00
Trevor Payne
5d1aa3b024 Added a null check to determining SIP information
Resolves #290
2020-06-30 11:01:46 -05:00
Andrew Welker
f6286cb5c1 Merge pull request #286 from jonavila/bugfix/fix-remote-registration
Resolves #262
2020-06-29 15:27:22 -06:00
Andrew Welker
2d7b2c05c5 Merge branch 'development' into bugfix/fix-remote-registration 2020-06-29 15:05:19 -06:00
Andrew Welker
9f8542049c Merge pull request #288 from PepperDash/feature/action-updates
Update Actions to add a PR-triggered action for Dev only
2020-06-29 15:04:53 -06:00
Andrew Welker
a26c951dba add logic to add pr postfix for pr triggered builds 2020-06-29 14:47:54 -06:00
Andrew Welker
83ca3ee350 printing things in powershell 2020-06-29 14:34:23 -06:00
Andrew Welker
acdff4ad67 add string IsNullOrEmpty check 2020-06-29 14:31:05 -06:00
Andrew Welker
708d4c266e adding some print info back 2020-06-29 14:28:02 -06:00
Andrew Welker
6160580f08 removed submodule checkout and moved it to checkout action 2020-06-29 14:26:43 -06:00
Andrew Welker
c7363c6434 removed print step 2020-06-29 14:20:36 -06:00
Andrew Welker
5f04190e6a removed info print name 2020-06-29 14:19:28 -06:00
Andrew Welker
6b908e18de updating script for forked builds 2020-06-29 14:18:14 -06:00
Andrew Welker
4d4230d9f4 getting all env variables 2020-06-29 14:13:43 -06:00
Andrew Welker
2e788d1917 figuring out what ref to use 2020-06-29 14:05:44 -06:00
Andrew Welker
1f21b573e2 print GITHUB_REF 2020-06-29 13:57:00 -06:00
Andrew Welker
a03e6824c5 trying to get environment variables 2020-06-29 13:55:05 -06:00
Andrew Welker
67cdd8bfa6 add print env step 2020-06-29 13:52:44 -06:00
Andrew Welker
44f6b465d4 really fix expression syntax 2020-06-29 13:49:39 -06:00
Andrew Welker
48220b8fe9 fix expression syntax 2020-06-29 13:47:57 -06:00
Andrew Welker
51f5d7e07b added print info step 2020-06-29 13:46:26 -06:00
Andrew Welker
ea3cb6eb80 added check for GITHUB_REF 2020-06-29 13:42:13 -06:00
Andrew Welker
91464d8ec1 remove new workflow and add pull-request trigger to existing workflow 2020-06-29 13:35:24 -06:00
Andrew Welker
80c98c60ca changed master -> main and added pull-request workflow 2020-06-29 13:22:09 -06:00
Jonathan Avila
8d8899f9ac Resolves #262
Register device when using internal RF gateway
2020-06-27 15:44:51 -04:00
Trevor Payne
001933bac3 Change base class on HdMdNxM4kEController to be CrestronGenericBaseDevice
Add required Factory class to HdMdNxM4kEController

Fixes #280
2020-06-25 10:12:30 -05:00
Andrew Welker
8445656289 fix constructor to initialize feedback 2020-06-25 08:19:08 -06:00
Andrew Welker
e8a8d481aa Merge pull request #278 from PepperDash/feature/Update-CiscoSpark-ce9.13
Update CiscoSpark to work with ce9.13
2020-06-24 10:03:05 -06:00
Trevor Payne
fd1de75a1d Updated CiscoSpark to work with ce9.13
Resolves #277
2020-06-24 10:44:57 -05:00
Neil Dorin
377cf23bca Merge pull request #274 from PepperDash/release/1.5.6
Release V1.5.6
2020-06-23 14:14:35 -06:00
142 changed files with 4859 additions and 7009 deletions

View File

@@ -1,5 +1,8 @@
$latestVersions = $(git tag --merged origin/main)
$latestVersion = [version]"0.0.0"
Write-Host "GITHUB_REF: $($Env:GITHUB_REF)"
Write-Host "GITHUB_HEAD_REF: $($Env:GITHUB_HEAD_REF)"
Write-Host "GITHUB_BASE_REF: $($Env:GITHUB_BASE_REF)"
Foreach ($version in $latestVersions) {
Write-Host $version
try {
@@ -17,7 +20,13 @@ Foreach ($version in $latestVersions) {
$newVersion = [version]$latestVersion
$phase = ""
$newVersionString = ""
switch -regex ($Env:GITHUB_REF) {
'^refs\/pull\/*.' {
$splitRef = $Env:GITHUB_REF -split "/"
$phase = "pr$($splitRef[2])"
$newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER
}
'^refs\/heads\/main*.' {
$newVersionString = "{0}.{1}.{2}" -f $newVersion.Major, $newVersion.Minor, $newVersion.Build
}
@@ -43,6 +52,7 @@ switch -regex ($Env:GITHUB_REF) {
$phase = 'hotfix'
$newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER
}
}

View File

@@ -8,6 +8,9 @@ on:
- bugfix/*
- release/*
- development
pull_request:
branches:
- development
env:
# solution path doesn't need slashes unless there it is multiple folders deep
@@ -29,14 +32,7 @@ jobs:
uses: actions/checkout@v2
with:
fetch-depth: 0
# 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
submodules: true
# Fetch all tags
- name: Fetch tags
run: git fetch --tags

View File

@@ -6,8 +6,8 @@ using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core.Devices.AudioCodec;
using PepperDash.Essentials.Core.Devices.Codec;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
namespace PepperDash.Essentials.AppServer.Messengers

View File

@@ -6,7 +6,6 @@ using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Rooms;
namespace PepperDash.Essentials.AppServer.Messengers

View File

@@ -9,7 +9,7 @@ using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.Devices.Codec;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
namespace PepperDash.Essentials.AppServer.Messengers

View File

@@ -8,7 +8,7 @@ using Crestron.SimplSharpPro.EthernetCommunication;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Devices.Codec;
using PepperDash.Essentials.Devices.Common.Codec;
namespace PepperDash.Essentials.AppServer.Messengers
{

View File

@@ -8,7 +8,7 @@ using Crestron.SimplSharpPro.EthernetCommunication;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Devices.Codec;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.Cameras;
namespace PepperDash.Essentials.AppServer.Messengers

View File

@@ -9,11 +9,9 @@ using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.Devices.Codec;
using PepperDash.Essentials.Core.Devices.VideoCodec;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.Cameras;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Core.VideoCodec;
namespace PepperDash.Essentials.AppServer.Messengers
{

View File

@@ -1,14 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Devices.AudioCodec;
using PepperDash.Essentials.Core.Devices.VideoCodec;
using PepperDash.Essentials.Core.Rooms;
using PepperDash.Essentials.Room.MobileControl;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
namespace PepperDash.Essentials
{

View File

@@ -14,7 +14,7 @@ using PepperDash.Essentials.AppServer;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Rooms.Config;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.Room.MobileControl
@@ -522,18 +522,18 @@ namespace PepperDash.Essentials.Room.MobileControl
// Build "audioCodec" config if we need
if (!string.IsNullOrEmpty(rmProps.AudioCodecKey))
{
var acFavs = new List<Core.Devices.Codec.CodecActiveCallItem>();
var acFavs = new List<PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem>();
for (uint i = 0; i < 4; i++)
{
if (!EISC.GetBool(JoinMap.SpeedDialVisibleStartJoin.JoinNumber + i))
{
break;
}
acFavs.Add(new Core.Devices.Codec.CodecActiveCallItem()
acFavs.Add(new PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem()
{
Name = EISC.GetString(JoinMap.SpeedDialNameStartJoin.JoinNumber + i),
Number = EISC.GetString(JoinMap.SpeedDialNumberStartJoin.JoinNumber + i),
Type = Core.Devices.Codec.eCodecCallType.Audio
Type = PepperDash.Essentials.Devices.Common.Codec.eCodecCallType.Audio
});
}
@@ -558,7 +558,7 @@ namespace PepperDash.Essentials.Room.MobileControl
if (!string.IsNullOrEmpty(rmProps.VideoCodecKey))
{
// No favorites, for now?
var favs = new List<Core.Devices.Codec.CodecActiveCallItem>();
var favs = new List<PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem>();
// cameras
var camsProps = new List<object>();

View File

@@ -27,8 +27,6 @@ namespace PepperDash.Essentials.Bridges
Eisc.SigChange += Eisc_SigChange;
Eisc.Register();
AddPostActivationAction(() =>
{
Debug.Console(1, this, "Linking Devices...");
@@ -77,6 +75,15 @@ namespace PepperDash.Essentials.Bridges
}
Debug.Console(1, this, "Devices Linked.");
var registerResult = Eisc.Register();
if (registerResult != eDeviceRegistrationUnRegistrationResponse.Success)
{
Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Registration result: {0}", registerResult);
return;
}
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "EISC registration successful");
});
}
@@ -151,12 +158,12 @@ namespace PepperDash.Essentials.Bridges
try
{
if (Debug.Level >= 1)
Debug.Console(1, this, "EiscApi change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
Debug.Console(2, this, "EiscApi change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
var uo = args.Sig.UserObject;
if (uo == null) return;
Debug.Console(1, this, "Executing Action: {0}", uo.ToString());
Debug.Console(2, this, "Executing Action: {0}", uo.ToString());
if (uo is Action<bool>)
(uo as Action<bool>)(args.Sig.BoolValue);
else if (uo is Action<ushort>)

View File

@@ -12,9 +12,12 @@ using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Rooms.Config;
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;
namespace PepperDash.Essentials
@@ -32,6 +35,7 @@ namespace PepperDash.Essentials
Thread.MaxNumberOfUserThreads = 400;
Global.ControlSystem = this;
DeviceManager.Initialize(this);
SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true;
}
/// <summary>
@@ -87,7 +91,12 @@ namespace PepperDash.Essentials
if (!Debug.DoNotLoadOnNextBoot)
{
GoWithLoad();
return;
}
SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true;
}
/// <summary>
@@ -165,7 +174,7 @@ namespace PepperDash.Essentials
public void GoWithLoad()
{
try
{
{
Debug.SetDoNotLoadOnNextBoot(false);
PluginLoader.AddProgramAssemblies();
@@ -185,11 +194,14 @@ namespace PepperDash.Essentials
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Folder structure verified. Loading config...");
if (!ConfigReader.LoadConfig2())
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Essentials Load complete with errors");
return;
}
Load();
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Essentials load complete\r" +
"-------------------------------------------------------------");
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Essentials load complete\r\n" +
"-------------------------------------------------------------");
}
else
{
@@ -208,11 +220,13 @@ namespace PepperDash.Essentials
}
catch (Exception e)
{
Debug.Console(0, "FATAL INITIALIZE ERROR. System is in an inconsistent state:\r{0}", e);
Debug.Console(0, "FATAL INITIALIZE ERROR. System is in an inconsistent state:\r\n{0}", e);
}
finally
{
// Notify the OS that the program intitialization has completed
SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true;
}
// Notify the OS that the program intitialization has completed
SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true;
}

View File

@@ -175,6 +175,10 @@
{
"deviceKey": "gls-odt-1",
"joinStart": 2751
},
{
"deviceKey": "gls-part-1",
"joinStart": 2781
}
]
}
@@ -427,6 +431,19 @@
"method": "cresnet"
}
}
},
{
"key": "gls-part-1",
"uid": 19,
"name": "GLS-PART-CN 1",
"type": "glspartcn",
"group": "partition",
"properties": {
"control": {
"cresnetId": "90",
"method": "cresnet"
}
}
}
],
"rooms": [],

View File

@@ -1,23 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using System;
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.Fusion;
using PepperDash.Core;
using PepperDash.Essentials;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Fusion;
using PepperDash.Essentials.Devices.Common;
using PepperDash.Essentials.Devices.Common.Occupancy;
using PepperDash.Essentials.Core.Fusion;
namespace PepperDash.Essentials.Fusion
{
public class EssentialsHuddleVtc1FusionController : EssentialsHuddleSpaceFusionSystemControllerBase
@@ -69,7 +61,7 @@ namespace PepperDash.Essentials.Fusion
// In Call Status
CodecIsInCall = FusionRoom.CreateOffsetBoolSig(69, "Conf - VC 1 In Call", eSigIoMask.InputSigOnly);
codec.CallStatusChange += new EventHandler<Core.Devices.Codec.CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
codec.CallStatusChange += new EventHandler<PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
// Online status
if (codec is ICommunicationMonitor)
@@ -147,7 +139,7 @@ namespace PepperDash.Essentials.Fusion
}
}
void codec_CallStatusChange(object sender, Core.Devices.Codec.CodecCallStatusItemChangeEventArgs e)
void codec_CallStatusChange(object sender, PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs e)
{
var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;

View File

@@ -123,6 +123,7 @@
<Compile Include="AppServer\SIMPLJoinMaps\SIMPLVtcJoinMap.cs" />
<Compile Include="AppServer\SIMPLJoinMaps\SIMPLAtcJoinMap.cs" />
<Compile Include="AppServer\SIMPLJoinMaps\MobileControlSIMPLRoomJoinMap.cs" />
<Compile Include="Audio\EssentialsVolumeLevelConfig.cs" />
<Compile Include="Bridges\EiscBridge.cs" />
<Compile Include="Bridges\JoinMaps\AirMediaControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\AppleTvJoinMap.cs" />
@@ -152,6 +153,13 @@
<Compile Include="ControlSystem.cs" />
<Compile Include="Fusion\EssentialsHuddleVtc1FusionController.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Room\Config\EssentialsDualDisplayRoomPropertiesConfig.cs" />
<Compile Include="Room\Config\EssentialsNDisplayRoomPropertiesConfig.cs" />
<Compile Include="Room\Config\DDVC01RoomPropertiesConfig.cs" />
<Compile Include="Room\Config\EssentialsPresentationPropertiesConfig.cs" />
<Compile Include="Room\Config\EssentialsHuddleRoomPropertiesConfig.cs" />
<Compile Include="Room\Config\EssentialsHuddleVtc1PropertiesConfig.cs" />
<Compile Include="Room\Config\EssentialsRoomEmergencyConfig.cs" />
<Compile Include="AppServer\MobileControlConfig.cs" />
<Compile Include="AppServer\MobileControlDdvc01DeviceBridge.cs" />
<Compile Include="AppServer\Interfaces.cs" />
@@ -168,6 +176,11 @@
<Compile Include="AppServer\DeviceTypeInterfaces\ITransportExtensions.cs" />
<Compile Include="AppServer\RoomBridges\SourceDeviceMapDictionary.cs" />
<Compile Include="AppServer\Volumes.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="UIDrivers\Environment Drivers\EssentialsEnvironmentDriver.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsLightingDriver.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsShadeDriver.cs" />
@@ -197,6 +210,7 @@
<Compile Include="AppServer\MobileControlSystemController.cs" />
<Compile Include="UI\DualDisplaySourceSRLController.cs" />
<Compile Include="UI\SubpageReferenceListActivityItem.cs" />
<Compile Include="Room\Types\EssentialsHuddleSpaceRoom.cs" />
<Compile Include="UI\EssentialsTouchpanelController.cs" />
<Compile Include="UI\SubpageReferenceListSourceItem.cs" />
<None Include="app.config" />
@@ -233,9 +247,6 @@
<Name>Essentials Devices Common</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="UIDrivers\EssentialsDualDisplay\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CompactFramework.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>

View File

@@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
@@ -74,8 +77,9 @@ namespace PepperDash.Essentials
var leftDisp = LeftDisplay as DisplayBase;
var rightDisp = RightDisplay as DisplayBase;
if (leftDisp != null && RightDisplay != null)
return rightDisp != null && (leftDisp.IsWarmingUpFeedback.BoolValue || rightDisp.IsWarmingUpFeedback.BoolValue);
return false;
return leftDisp.IsWarmingUpFeedback.BoolValue || rightDisp.IsWarmingUpFeedback.BoolValue;
else
return false;
};
}
}
@@ -92,8 +96,9 @@ namespace PepperDash.Essentials
var leftDisp = LeftDisplay as DisplayBase;
var rightDisp = RightDisplay as DisplayBase;
if (leftDisp != null && RightDisplay != null)
return rightDisp != null && (leftDisp.IsCoolingDownFeedback.BoolValue || rightDisp.IsCoolingDownFeedback.BoolValue);
return false;
return leftDisp.IsCoolingDownFeedback.BoolValue || rightDisp.IsCoolingDownFeedback.BoolValue;
else
return false;
};
}
}
@@ -115,7 +120,7 @@ namespace PepperDash.Essentials
/// If room is off, enables power on to last source. Default true
/// </summary>
public bool EnablePowerOnToLastSource { get; set; }
string _lastSourceKey;
string LastSourceKey;
/// <summary>
/// Sets the volume control device, and attaches/removes InUseTrackers with "audio"
@@ -123,27 +128,27 @@ namespace PepperDash.Essentials
/// </summary>
public IBasicVolumeControls CurrentVolumeControls
{
get { return _currentAudioDevice; }
get { return _CurrentAudioDevice; }
set
{
if (value == _currentAudioDevice) return;
if (value == _CurrentAudioDevice) return;
var oldDev = _currentAudioDevice;
var oldDev = _CurrentAudioDevice;
// derigister this room from the device, if it can
if (oldDev is IInUseTracking)
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
var handler = CurrentVolumeDeviceChange;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
_currentAudioDevice = value;
_CurrentAudioDevice = value;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
// register this room with new device, if it can
if (_currentAudioDevice is IInUseTracking)
(_currentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
if (_CurrentAudioDevice is IInUseTracking)
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
}
}
IBasicVolumeControls _currentAudioDevice;
IBasicVolumeControls _CurrentAudioDevice;
/// <summary>
/// "codecOsd"
@@ -156,7 +161,7 @@ namespace PepperDash.Essentials
/// </summary>
public IHasScheduleAwareness ScheduleSource { get { return VideoCodec as IHasScheduleAwareness; } }
readonly CCriticalSection _sourceSelectLock = new CCriticalSection();
CCriticalSection SourceSelectLock = new CCriticalSection();
public EssentialsDualDisplayRoom(DeviceConfig config)
: base(config)
@@ -191,12 +196,12 @@ namespace PepperDash.Essentials
}
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
VideoCodecBase;
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
if (VideoCodec == null)
throw new ArgumentNullException("codec cannot be null");
AudioCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.AudioCodecKey) as
AudioCodecBase;
PepperDash.Essentials.Devices.Common.AudioCodec.AudioCodecBase;
if (AudioCodec == null)
Debug.Console(0, this, "No Audio Codec Found");
@@ -212,8 +217,8 @@ namespace PepperDash.Essentials
void Initialize()
{
if (DefaultAudioDevice != null)
DefaultVolumeControls = DefaultAudioDevice;
if (DefaultAudioDevice is IBasicVolumeControls)
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;
else if (DefaultAudioDevice is IHasVolumeDevice)
DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice;
CurrentVolumeControls = DefaultVolumeControls;
@@ -228,12 +233,12 @@ namespace PepperDash.Essentials
InitializeDisplay(rightDisp);
// Get Microphone Privacy object, if any
MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this);
this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this);
Debug.Console(2, this, "Microphone Privacy Config evaluated.");
// Get emergency object, if any
Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this);
this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this);
Debug.Console(2, this, "Emergency Config evaluated.");
@@ -249,20 +254,23 @@ namespace PepperDash.Essentials
if (VideoCodec != null)
inVideoCall = VideoCodec.IsInCall;
return inAudioCall || inVideoCall;
if (inAudioCall || inVideoCall)
return true;
else
return false;
});
VideoCodec.CallStatusChange += (o, a) => InCallFeedback.FireUpdate();
VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
if (AudioCodec != null)
AudioCodec.CallStatusChange += (o, a) => InCallFeedback.FireUpdate();
AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue);
VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => IsSharingFeedback.FireUpdate();
VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate();
// link privacy to VC (for now?)
PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue);
VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => PrivacyModeIsOnFeedback.FireUpdate();
VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate();
CallTypeFeedback = new IntFeedback(() => 0);
@@ -292,18 +300,13 @@ namespace PepperDash.Essentials
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
{
IsWarmingUpFeedback.FireUpdate();
if (IsWarmingUpFeedback.BoolValue)
{
return;
}
var basicVolumeWithFeedback = CurrentVolumeControls as IBasicVolumeWithFeedback;
if (basicVolumeWithFeedback != null)
{
basicVolumeWithFeedback.SetVolume(DefaultVolume);
}
if (!IsWarmingUpFeedback.BoolValue)
(CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
};
disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
{
IsCoolingDownFeedback.FireUpdate();
};
disp.IsCoolingDownFeedback.OutputChange += (o, a) => IsCoolingDownFeedback.FireUpdate();
}
}
@@ -321,13 +324,13 @@ namespace PepperDash.Essentials
{
// Add Occupancy object from config
if (PropertiesConfig.Occupancy != null)
SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
LogoUrl = PropertiesConfig.Logo.GetUrl();
SourceListKey = PropertiesConfig.SourceListKey;
DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
this.LogoUrl = PropertiesConfig.Logo.GetUrl();
this.SourceListKey = PropertiesConfig.SourceListKey;
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
return base.CustomActivate();
}
@@ -373,7 +376,6 @@ namespace PepperDash.Essentials
///
/// </summary>
/// <param name="routeKey"></param>
/// <param name="sourceListKey"></param>
public void RunRouteAction(string routeKey, string sourceListKey)
{
RunRouteAction(routeKey, sourceListKey, null);
@@ -383,17 +385,14 @@ namespace PepperDash.Essentials
/// Gets a source from config list SourceListKey and dynamically build and executes the
/// route or commands
/// </summary>
/// <param name="routeKey"></param>
/// <param name="sourceListKey"></param>
/// <param name="successCallback"></param>
/// <param name="name"></param>
public void RunRouteAction(string routeKey, string sourceListKey, Action successCallback)
{
// Run this on a separate thread
//new CTimer
CrestronInvoke.BeginInvoke(o =>
new CTimer(o =>
{
// try to prevent multiple simultaneous selections
_sourceSelectLock.TryEnter();
SourceSelectLock.TryEnter();
try
{
@@ -415,9 +414,9 @@ namespace PepperDash.Essentials
}
// End usage timer on last source
if (!string.IsNullOrEmpty(_lastSourceKey))
if (!string.IsNullOrEmpty(LastSourceKey))
{
var usageLastSource = dict[_lastSourceKey].SourceDevice as IUsageTracking;
var usageLastSource = dict[LastSourceKey].SourceDevice as IUsageTracking;
if (usageLastSource != null && usageLastSource.UsageTracker != null)
{
try
@@ -437,7 +436,7 @@ namespace PepperDash.Essentials
if (routeKey.ToLower() != "roomoff")
{
_lastSourceKey = routeKey;
LastSourceKey = routeKey;
}
//else
// CurrentSourceInfoKey = null;
@@ -522,7 +521,7 @@ namespace PepperDash.Essentials
Debug.Console(1, this, "ERROR in routing: {0}", e);
}
_sourceSelectLock.Leave();
SourceSelectLock.Leave();
}, 0); // end of CTimer
}
@@ -531,8 +530,6 @@ namespace PepperDash.Essentials
///
/// </summary>
/// <param name="route"></param>
/// <param name="sourceItem"></param>
/// <param name="sourceItemKey"></param>
void DoRouteItem(SourceRouteListItem route, SourceListItem sourceItem, string sourceItemKey)
{
// if there is a $defaultAll on route, run two separate
@@ -556,7 +553,7 @@ namespace PepperDash.Essentials
/// </summary>
/// <param name="route"></param>
/// <returns></returns>
private bool DoRoute(SourceRouteListItem route, SourceListItem sourceItem, string sourceItemKey)
bool DoRoute(SourceRouteListItem route, SourceListItem sourceItem, string sourceItemKey)
{
IRoutingSink dest = null;
@@ -620,9 +617,9 @@ namespace PepperDash.Essentials
/// </summary>
public override void PowerOnToDefaultOrLastSource()
{
if (!EnablePowerOnToLastSource || _lastSourceKey == null)
if (!EnablePowerOnToLastSource || LastSourceKey == null)
return;
RunRouteAction(_lastSourceKey, SourceListKey);
RunRouteAction(LastSourceKey, SourceListKey);
}
/// <summary>
@@ -630,11 +627,10 @@ namespace PepperDash.Essentials
/// </summary>
public static void AllRoomsOff()
{
var allRooms = DeviceManager.AllDevices.OfType<EssentialsHuddleSpaceRoom>().Where(d => !d.ExcludeFromGlobalFunctions);
var allRooms = DeviceManager.AllDevices.Where(d =>
d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
foreach (var room in allRooms)
{
room.RunRouteAction("roomOff", room.SourceListKey);
}
(room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff", (room as EssentialsHuddleSpaceRoom).SourceListKey);
}
#region IPrivacy Members

View File

@@ -1,5 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
@@ -7,21 +13,148 @@ using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IRunRouteAction,
IRunDefaultPresentRoute, IHasCurrentVolumeControls, IHasDefaultDisplay, IHasCurrentSourceInfoChange
{
public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasCurrentVolumeControls, IHasDefaultDisplay
{
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
public event SourceInfoChangeHandler CurrentSourceChange;
protected override Func<bool> OnFeedbackFunc
{
get
{
return () =>
{
var disp = DefaultDisplay as DisplayBase;
var val = CurrentSourceInfo != null
&& CurrentSourceInfo.Type == eSourceListItemType.Route
&& disp != null;
//&& disp.PowerIsOnFeedback.BoolValue;
return val;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsWarmingFeedbackFunc
{
get
{
return () =>
{
var disp = DefaultDisplay as DisplayBase;
if (disp != null)
return disp.IsWarmingUpFeedback.BoolValue;
else
return false;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsCoolingFeedbackFunc
{
get
{
return () =>
{
var disp = DefaultDisplay as DisplayBase;
if (disp != null)
return disp.IsCoolingDownFeedback.BoolValue;
else
return false;
};
}
}
public EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; private set; }
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
public IRoutingSink DefaultAudioDevice { get; private set; }
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
public bool ExcludeFromGlobalFunctions { get; set; }
public string DefaultSourceItem { get; set; }
public ushort DefaultVolume { get; set; }
/// <summary>
/// If room is off, enables power on to last source. Default true
/// </summary>
public bool EnablePowerOnToLastSource { get; set; }
string LastSourceKey;
/// <summary>
///
/// </summary>
public IBasicVolumeControls CurrentVolumeControls
{
get { return _CurrentAudioDevice; }
set
{
if (value == _CurrentAudioDevice) return;
var oldDev = _CurrentAudioDevice;
// derigister this room from the device, if it can
if (oldDev is IInUseTracking)
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
var handler = CurrentVolumeDeviceChange;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
_CurrentAudioDevice = value;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
// register this room with new device, if it can
if (_CurrentAudioDevice is IInUseTracking)
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
}
}
IBasicVolumeControls _CurrentAudioDevice;
/// <summary>
/// The SourceListItem last run - containing names and icons
/// </summary>
public SourceListItem CurrentSourceInfo
{
get { return _CurrentSourceInfo; }
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
// remove from in-use tracker, if so equipped
if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
// add to in-use tracking
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
if (handler != null)
handler( _CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
public string CurrentSourceInfoKey { get; set; }
public EssentialsHuddleSpaceRoom(DeviceConfig config)
: base(config)
{
try
{
PropertiesConfig = config.Properties.ToObject<EssentialsHuddleRoomPropertiesConfig>();
DefaultDisplay =
DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching;
//why are we assuming IRoutingSinkWithSwitching here?
PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleRoomPropertiesConfig>
(config.Properties.ToString());
DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching;
DefaultAudioDevice =
DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IRoutingSinkWithSwitching;
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IRoutingSinkWithSwitching;
Initialize();
}
@@ -31,122 +164,361 @@ namespace PepperDash.Essentials
}
}
public EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; private set; }
private void Initialize()
{
void Initialize()
{
if (DefaultAudioDevice is IBasicVolumeControls)
{
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;
}
else if (DefaultAudioDevice is IHasVolumeDevice)
{
DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice;
}
CurrentVolumeControls = DefaultVolumeControls;
SourceListKey = String.IsNullOrEmpty(PropertiesConfig.SourceListKey)
? "default"
: PropertiesConfig.SourceListKey;
EnablePowerOnToLastSource = true;
var disp = DefaultDisplay as DisplayBase;
if (disp == null)
if (disp != null)
{
return;
// 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();
}
};
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
{
IsWarmingUpFeedback.FireUpdate();
if (!IsWarmingUpFeedback.BoolValue)
(DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
};
disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
{
IsCoolingDownFeedback.FireUpdate();
};
}
IsWarmingFeedbackFunc = () => disp.IsWarmingUpFeedback.BoolValue;
IsCoolingFeedbackFunc = () => disp.IsCoolingDownFeedback.BoolValue;
OnFeedbackFunc = () => CurrentSourceInfo != null
&& CurrentSourceInfo.Type == eSourceListItemType.Route;
InitializeDisplay(disp);
}
protected override void IsCoolingDownFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
{
IsCoolingDownFeedback.FireUpdate();
}
protected override void PowerIsOnFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
{
var display = sender as DisplayBase;
if (display == null)
{
return;
}
if (display.PowerIsOnFeedback.BoolValue == OnFeedback.BoolValue)
{
return;
}
if (!display.PowerIsOnFeedback.BoolValue)
{
CurrentSourceInfo = null;
}
OnFeedback.FireUpdate();
}
protected override void IsWarmingUpFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
{
IsWarmingUpFeedback.FireUpdate();
if (IsWarmingUpFeedback.BoolValue)
{
return;
}
var displayVolumeControl = DefaultDisplay as IBasicVolumeWithFeedback;
if (displayVolumeControl == null)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Error,
"Default display {0} is not volume control control provider", DefaultDisplay.Key);
return;
}
displayVolumeControl.SetVolume(DefaultVolume);
}
SourceListKey = "default";
EnablePowerOnToLastSource = true;
}
protected override void CustomSetConfig(DeviceConfig config)
{
var newPropertiesConfig =
JsonConvert.DeserializeObject<EssentialsHuddleRoomPropertiesConfig>(config.Properties.ToString());
var newPropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleRoomPropertiesConfig>(config.Properties.ToString());
if (newPropertiesConfig != null)
{
PropertiesConfig = newPropertiesConfig;
}
ConfigWriter.UpdateRoomConfig(config);
}
/// <summary>
///
/// </summary>
protected override void EndShutdown()
{
SetDefaultLevels();
RunDefaultPresentRoute();
CrestronEnvironment.Sleep(1000);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room");
RunRouteAction("roomOff");
}
/// <summary>
/// Routes the default source item, if any
/// </summary>
public override bool RunDefaultPresentRoute()
{
if (DefaultSourceItem == null)
{
Debug.Console(0, this, "Unable to run default present route, DefaultSourceItem is null.");
return false;
}
RunRouteAction(DefaultSourceItem);
return true;
}
public override bool CustomActivate()
{
// Add Occupancy object from config
if (PropertiesConfig.Occupancy != null)
{
SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
}
LogoUrl = PropertiesConfig.Logo.GetUrl();
SourceListKey = PropertiesConfig.SourceListKey;
DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
DefaultVolume = (ushort) (PropertiesConfig.Volumes.Master.Level*65535/100);
this.LogoUrl = PropertiesConfig.Logo.GetUrl();
this.SourceListKey = PropertiesConfig.SourceListKey;
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
return base.CustomActivate();
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
public void RunRouteAction(string routeKey)
{
RunRouteAction(routeKey, new Action(() => { }));
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
/// <param name="souceListKey"></param>
/// <param name="successCallback"></param>
public void RunRouteAction(string routeKey, string souceListKey)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
/// <param name="souceListKey"></param>
/// <param name="successCallback"></param>
public void RunRouteAction(string routeKey, string souceListKey, Action successCallback)
{
throw new NotImplementedException();
}
/// <summary>
/// Gets a source from config list SourceListKey and dynamically build and executes the
/// route or commands
/// </summary>
/// <param name="name"></param>
public void RunRouteAction(string routeKey, Action successCallback)
{
// Run this on a separate thread
new CTimer(o =>
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Run route action '{0}'", routeKey);
var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
if(dict == null)
{
Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
return;
}
// Try to get the list item by it's string key
if (!dict.ContainsKey(routeKey))
{
Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
routeKey, SourceListKey);
return;
}
var item = dict[routeKey];
//Debug.Console(2, this, "Action {0} has {1} steps",
// item.SourceKey, item.RouteList.Count);
// End usage timer on last source
if (!string.IsNullOrEmpty(LastSourceKey))
{
var lastSource = dict[LastSourceKey].SourceDevice;
try
{
if (lastSource != null && lastSource is IUsageTracking)
(lastSource as IUsageTracking).UsageTracker.EndDeviceUsage();
}
catch (Exception e)
{
Debug.Console(1, this, "*#* EXCEPTION in end usage tracking (257):\r{0}", e);
}
}
// Let's run it
if (routeKey.ToLower() != "roomoff")
{
LastSourceKey = routeKey;
}
else
{
CurrentSourceInfoKey = null;
}
foreach (var route in item.RouteList)
{
// if there is a $defaultAll on route, run two separate
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
{
// Going to assume a single-path route for now
var tempVideo = new SourceRouteListItem
{
DestinationKey = "$defaultDisplay",
SourceKey = route.SourceKey,
Type = eRoutingSignalType.Video
};
DoRoute(tempVideo);
//var tempAudio = new SourceRouteListItem
//{
// DestinationKey = "$defaultAudio",
// SourceKey = route.SourceKey,
// Type = eRoutingSignalType.Audio
//};
//DoRoute(tempAudio);
//continue; -- not sure why this was here
}
else
DoRoute(route);
}
// Start usage timer on routed source
if (item.SourceDevice is IUsageTracking)
{
(item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
}
// Set volume control, using default if non provided
IBasicVolumeControls volDev = null;
// Handle special cases for volume control
if (string.IsNullOrEmpty(item.VolumeControlKey)
|| item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
volDev = DefaultVolumeControls;
else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
volDev = DefaultDisplay as IBasicVolumeControls;
// Or a specific device, probably rarely used.
else
{
var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
if (dev is IBasicVolumeControls)
volDev = dev as IBasicVolumeControls;
else if (dev is IHasVolumeDevice)
volDev = (dev as IHasVolumeDevice).VolumeDevice;
}
if (volDev != CurrentVolumeControls)
{
// zero the volume on the device we are leaving.
// Set the volume to default on device we are entering
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
SavedVolumeLevels[vd] = (uint)vd.VolumeLevelFeedback.IntValue;
vd.SetVolume(0);
}
CurrentVolumeControls = volDev;
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume);
vd.SetVolume(vol);
}
}
// store the name and UI info for routes
if (item.SourceKey == "$off")
{
CurrentSourceInfoKey = routeKey;
CurrentSourceInfo = null;
}
else if (item.SourceKey != null)
{
CurrentSourceInfoKey = routeKey;
CurrentSourceInfo = item;
}
// And finally, set the "control". This will trigger event
//CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device;
OnFeedback.FireUpdate();
// report back when done
if (successCallback != null)
successCallback();
}, 0); // end of CTimer
}
/// <summary>
/// Will power the room on with the last-used source
/// </summary>
public override void PowerOnToDefaultOrLastSource()
{
if (!EnablePowerOnToLastSource || LastSourceKey == null)
return;
RunRouteAction(LastSourceKey);
}
/// <summary>
/// Does what it says
/// </summary>
public override void SetDefaultLevels()
{
Debug.Console(1, this, "Restoring default levels");
var vc = CurrentVolumeControls as IBasicVolumeWithFeedback;
if (vc != null)
vc.SetVolume(DefaultVolume);
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
/// <returns></returns>
bool DoRoute(SourceRouteListItem route)
{
IRoutingSink dest = null;
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
dest = DefaultAudioDevice;
else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
dest = DefaultDisplay;
else
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink;
if (dest == null)
{
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
return false;
}
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
{
dest.ReleaseRoute();
if (dest is IPower)
(dest as IPower).PowerOff();
}
else
{
var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
if (source == null)
{
Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
return false;
}
dest.ReleaseAndMakeRoute(source, route.Type);
}
return true;
}
public override void RoomVacatedForTimeoutPeriod(object o)
{
//TODO: Implement RoomVacatedForTimeoutPeriod
//Implement this
}
}
/// <summary>
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
/// </summary>
public static void AllRoomsOff()
{
var allRooms = DeviceManager.AllDevices.Where(d =>
d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
foreach (var room in allRooms)
(room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
}
}
}

View File

@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
@@ -47,7 +49,58 @@ namespace PepperDash.Essentials
public BoolFeedback IsSharingFeedback { get; private set; }
//************************
protected override Func<bool> OnFeedbackFunc
{
get
{
return () =>
{
var disp = DefaultDisplay as DisplayBase;
var val = CurrentSourceInfo != null
&& CurrentSourceInfo.Type == eSourceListItemType.Route
&& disp != null;
//&& disp.PowerIsOnFeedback.BoolValue;
return val;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsWarmingFeedbackFunc
{
get
{
return () =>
{
var disp = DefaultDisplay as DisplayBase;
if (disp != null)
return disp.IsWarmingUpFeedback.BoolValue;
else
return false;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsCoolingFeedbackFunc
{
get
{
return () =>
{
var disp = DefaultDisplay as DisplayBase;
if (disp != null)
return disp.IsCoolingDownFeedback.BoolValue;
else
return false;
};
}
}
public EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; private set; }
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
@@ -68,36 +121,64 @@ namespace PepperDash.Essentials
/// If room is off, enables power on to last source. Default true
/// </summary>
public bool EnablePowerOnToLastSource { get; set; }
private string _lastSourceKey;
string LastSourceKey;
/// <summary>
/// Sets the volume control device, and attaches/removes InUseTrackers with "audio"
/// tag to device.
/// </summary>
public IBasicVolumeControls CurrentVolumeControls
{
get { return _CurrentAudioDevice; }
set
{
if (value == _CurrentAudioDevice) return;
var oldDev = _CurrentAudioDevice;
// derigister this room from the device, if it can
if (oldDev is IInUseTracking)
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
var handler = CurrentVolumeDeviceChange;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
_CurrentAudioDevice = value;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
// register this room with new device, if it can
if (_CurrentAudioDevice is IInUseTracking)
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
}
}
IBasicVolumeControls _CurrentAudioDevice;
/// <summary>
/// The SourceListItem last run - containing names and icons
/// </summary>
public SourceListItem CurrentSourceInfo
{
get { return _currentSourceInfo; }
get { return _CurrentSourceInfo; }
set
{
if (value == _currentSourceInfo) return;
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
// remove from in-use tracker, if so equipped
if(_currentSourceInfo != null && _currentSourceInfo.SourceDevice is IInUseTracking)
(_currentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
if (handler != null)
handler(_currentSourceInfo, ChangeType.WillChange);
handler(_CurrentSourceInfo, ChangeType.WillChange);
_currentSourceInfo = value;
_CurrentSourceInfo = value;
// add to in-use tracking
if (_currentSourceInfo != null && _currentSourceInfo.SourceDevice is IInUseTracking)
(_currentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
if (handler != null)
handler(_currentSourceInfo, ChangeType.DidChange);
handler(_CurrentSourceInfo, ChangeType.DidChange);
}
}
private SourceListItem _currentSourceInfo;
SourceListItem _CurrentSourceInfo;
public string CurrentSourceInfoKey { get; set; }
@@ -112,7 +193,7 @@ namespace PepperDash.Essentials
/// </summary>
public IHasScheduleAwareness ScheduleSource { get { return VideoCodec as IHasScheduleAwareness; } }
private readonly CCriticalSection _sourceSelectLock = new CCriticalSection();
CCriticalSection SourceSelectLock = new CCriticalSection();
public EssentialsHuddleVtc1Room(DeviceConfig config)
: base(config)
@@ -124,12 +205,12 @@ namespace PepperDash.Essentials
DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching;
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
VideoCodecBase;
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
if (VideoCodec == null)
throw new ArgumentNullException("codec cannot be null");
AudioCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.AudioCodecKey) as
AudioCodecBase;
PepperDash.Essentials.Devices.Common.AudioCodec.AudioCodecBase;
if (AudioCodec == null)
Debug.Console(0, this, "No Audio Codec Found");
@@ -147,8 +228,8 @@ namespace PepperDash.Essentials
{
try
{
if (DefaultAudioDevice != null)
DefaultVolumeControls = DefaultAudioDevice;
if (DefaultAudioDevice is IBasicVolumeControls)
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;
else if (DefaultAudioDevice is IHasVolumeDevice)
DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice;
CurrentVolumeControls = DefaultVolumeControls;
@@ -157,8 +238,8 @@ namespace PepperDash.Essentials
// Combines call feedback from both codecs if available
InCallFeedback = new BoolFeedback(() =>
{
var inAudioCall = false;
var inVideoCall = false;
bool inAudioCall = false;
bool inVideoCall = false;
if (AudioCodec != null)
inAudioCall = AudioCodec.IsInCall;
@@ -166,48 +247,72 @@ namespace PepperDash.Essentials
if (VideoCodec != null)
inVideoCall = VideoCodec.IsInCall;
return inAudioCall || inVideoCall;
if (inAudioCall || inVideoCall)
return true;
else
return false;
});
var disp = DefaultDisplay as DisplayBase;
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();
}
if (disp.PowerIsOnFeedback.BoolValue)
{
SetDefaultLevels();
}
};
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
{
IsWarmingUpFeedback.FireUpdate();
if (!IsWarmingUpFeedback.BoolValue)
(CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
};
disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
{
IsCoolingDownFeedback.FireUpdate();
};
}
// Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback
MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this);
this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this);
Debug.Console(2, this, "Microphone Privacy Config evaluated.");
// Get emergency object, if any
Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this);
this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this);
Debug.Console(2, this, "Emergency Config evaluated.");
VideoCodec.CallStatusChange += (o, a) => InCallFeedback.FireUpdate();
VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
if (AudioCodec != null)
AudioCodec.CallStatusChange += (o, a) => InCallFeedback.FireUpdate();
AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue);
VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => IsSharingFeedback.FireUpdate();
VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate();
// link privacy to VC (for now?)
PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue);
VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => PrivacyModeIsOnFeedback.FireUpdate();
VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate();
CallTypeFeedback = new IntFeedback(() => 0);
SourceListKey = "default";
EnablePowerOnToLastSource = true;
var disp = DefaultDisplay as DisplayBase;
if (disp == null)
{
return;
}
OnFeedbackFunc = () => CurrentSourceInfo != null
&& CurrentSourceInfo.Type == eSourceListItemType.Route;
InitializeDisplay(disp);
}
catch (Exception e)
{
@@ -215,50 +320,6 @@ namespace PepperDash.Essentials
}
}
#region Overrides of EssentialsRoomBase
protected override void PowerIsOnFeedbackOnOutputChange(object sender, FeedbackEventArgs args)
{
var disp = sender as DisplayBase;
if (disp == null) return;
if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
{
if (!disp.PowerIsOnFeedback.BoolValue)
CurrentSourceInfo = null;
OnFeedback.FireUpdate();
}
if (disp.PowerIsOnFeedback.BoolValue)
{
SetDefaultLevels();
}
}
protected override void IsCoolingDownFeedbackOnOutputChange(object sender, FeedbackEventArgs args)
{
IsCoolingDownFeedback.FireUpdate();
}
protected override void IsWarmingUpFeedbackOnOutputChange(object sender, FeedbackEventArgs args)
{
IsWarmingUpFeedback.FireUpdate();
if (IsWarmingUpFeedback.BoolValue)
{
return;
}
var basicVolumeWithFeedback = CurrentVolumeControls as IBasicVolumeWithFeedback;
if (basicVolumeWithFeedback != null)
{
basicVolumeWithFeedback.SetVolume(DefaultVolume);
}
}
#endregion
protected override void CustomSetConfig(DeviceConfig config)
{
var newPropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>(config.Properties.ToString());
@@ -275,14 +336,14 @@ namespace PepperDash.Essentials
if (PropertiesConfig.Occupancy != null)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room");
SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
}
LogoUrl = PropertiesConfig.Logo.GetUrl();
SourceListKey = PropertiesConfig.SourceListKey;
DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
this.LogoUrl = PropertiesConfig.Logo.GetUrl();
this.SourceListKey = PropertiesConfig.SourceListKey;
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
return base.CustomActivate();
}
@@ -331,9 +392,9 @@ namespace PepperDash.Essentials
///
/// </summary>
/// <param name="routeKey"></param>
public override void RunRouteAction(string routeKey)
public void RunRouteAction(string routeKey)
{
RunRouteAction(routeKey, () => { });
RunRouteAction(routeKey, new Action(() => { }));
}
/// <summary>
@@ -341,6 +402,7 @@ namespace PepperDash.Essentials
/// </summary>
/// <param name="routeKey"></param>
/// <param name="souceListKey"></param>
/// <param name="successCallback"></param>
public void RunRouteAction(string routeKey, string souceListKey)
{
throw new NotImplementedException();
@@ -357,18 +419,18 @@ namespace PepperDash.Essentials
throw new NotImplementedException();
}
/// <summary>
/// Gets a source from config list SourceListKey and dynamically build and executes the
/// route or commands
/// </summary>
/// <summary>
/// Gets a source from config list SourceListKey and dynamically build and executes the
/// route or commands
/// </summary>
/// <param name="name"></param>
public void RunRouteAction(string routeKey, Action successCallback)
{
// Run this on a separate thread
//new CTimer
CrestronInvoke.BeginInvoke(o =>
new CTimer(o =>
{
// try to prevent multiple simultaneous selections
_sourceSelectLock.TryEnter();
SourceSelectLock.TryEnter();
try
{
@@ -390,9 +452,9 @@ namespace PepperDash.Essentials
}
// End usage timer on last source
if (!string.IsNullOrEmpty(_lastSourceKey))
if (!string.IsNullOrEmpty(LastSourceKey))
{
var usageLastSource = dict[_lastSourceKey].SourceDevice as IUsageTracking;
var usageLastSource = dict[LastSourceKey].SourceDevice as IUsageTracking;
if (usageLastSource != null && usageLastSource.UsageTracker != null)
{
try
@@ -412,7 +474,7 @@ namespace PepperDash.Essentials
if (routeKey.ToLower() != "roomoff")
{
_lastSourceKey = routeKey;
LastSourceKey = routeKey;
}
else
CurrentSourceInfoKey = null;
@@ -464,7 +526,7 @@ namespace PepperDash.Essentials
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
var vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume);
ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume);
vd.SetVolume(vol);
}
}
@@ -495,7 +557,7 @@ namespace PepperDash.Essentials
Debug.Console(1, this, "ERROR in routing: {0}", e);
}
_sourceSelectLock.Leave();
SourceSelectLock.Leave();
}, 0); // end of CTimer
}
@@ -526,9 +588,9 @@ namespace PepperDash.Essentials
/// </summary>
/// <param name="route"></param>
/// <returns></returns>
private bool DoRoute(SourceRouteListItem route)
bool DoRoute(SourceRouteListItem route)
{
IRoutingSink dest;
IRoutingSink dest = null;
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
dest = DefaultAudioDevice as IRoutingSinkNoSwitching;
@@ -582,9 +644,9 @@ namespace PepperDash.Essentials
/// </summary>
public override void PowerOnToDefaultOrLastSource()
{
if (!EnablePowerOnToLastSource || _lastSourceKey == null)
if (!EnablePowerOnToLastSource || LastSourceKey == null)
return;
RunRouteAction(_lastSourceKey);
RunRouteAction(LastSourceKey);
}
/// <summary>
@@ -595,13 +657,7 @@ namespace PepperDash.Essentials
var allRooms = DeviceManager.AllDevices.Where(d =>
d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
foreach (var room in allRooms)
{
var essentialsHuddleSpaceRoom = room as EssentialsHuddleSpaceRoom;
if (essentialsHuddleSpaceRoom != null)
{
essentialsHuddleSpaceRoom.RunRouteAction("roomOff");
}
}
(room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
}
#region IPrivacy Members

View File

@@ -1,6 +1,16 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
@@ -13,7 +23,7 @@ namespace PepperDash.Essentials
public Dictionary<eSourceListItemDestinationTypes, IRoutingSinkWithSwitching> Displays { get; protected set;}
protected EssentialsNDisplayRoomBase(DeviceConfig config)
public EssentialsNDisplayRoomBase(DeviceConfig config)
: base (config)
{
Displays = new Dictionary<eSourceListItemDestinationTypes, IRoutingSinkWithSwitching>();

View File

@@ -111,7 +111,7 @@ namespace PepperDash.Essentials
/// <summary>
/// Reads the device keys from the config and gets the devices by key
/// </summary>
public void GetDevicesFromConfig(Core.Rooms.Config.EssentialsEnvironmentPropertiesConfig EnvironmentPropertiesConfig)
public void GetDevicesFromConfig(Room.Config.EssentialsEnvironmentPropertiesConfig EnvironmentPropertiesConfig)
{
if (EnvironmentPropertiesConfig != null)
{

View File

@@ -10,11 +10,10 @@ using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Devices.VideoCodec;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.PageManagers;
using PepperDash.Essentials.Core.Rooms.Config;
using PepperDash.Essentials.Core.Devices.Codec;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;

View File

@@ -2,11 +2,13 @@
using System.Collections.Generic;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.UI;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.PageManagers;
using PepperDash.Essentials.UIDrivers;
namespace PepperDash.Essentials
{
@@ -15,7 +17,7 @@ namespace PepperDash.Essentials
/// </summary>
public class EssentialsHuddlePanelAvFunctionsDriver : PanelDriverBase, IAVDriver
{
private readonly CrestronTouchpanelPropertiesConfig _config;
CrestronTouchpanelPropertiesConfig Config;
public enum UiDisplayMode
{
@@ -33,8 +35,8 @@ namespace PepperDash.Essentials
/// </summary>
public uint VolumeButtonPopupTimeout
{
get { return _volumeButtonsPopupFeedback.TimeoutMs; }
set { _volumeButtonsPopupFeedback.TimeoutMs = value; }
get { return VolumeButtonsPopupFeedback.TimeoutMs; }
set { VolumeButtonsPopupFeedback.TimeoutMs = value; }
}
/// <summary>
@@ -42,8 +44,8 @@ namespace PepperDash.Essentials
/// </summary>
public uint VolumeGaugePopupTimeout
{
get { return _volumeGaugeFeedback.TimeoutMs; }
set { _volumeGaugeFeedback.TimeoutMs = value; }
get { return VolumeGaugeFeedback.TimeoutMs; }
set { VolumeGaugeFeedback.TimeoutMs = value; }
}
/// <summary>
@@ -51,12 +53,21 @@ namespace PepperDash.Essentials
/// </summary>
public uint PowerOffTimeout { get; set; }
/// <summary>
///
/// </summary>
public string DefaultRoomKey { get; set; }
/// <summary>
///
/// </summary>
public string DefaultRoomKey
{
get { return _DefaultRoomKey; }
set
{
_DefaultRoomKey = value;
//CurrentRoom = DeviceManager.GetDeviceForKey(value) as EssentialsHuddleSpaceRoom;
}
}
string _DefaultRoomKey;
/// <summary>
/// <summary>
/// Indicates that the SetHeaderButtons method has completed successfully
/// </summary>
public bool HeaderButtonsAreSetUp { get; private set; }
@@ -66,13 +77,13 @@ namespace PepperDash.Essentials
/// </summary>
public EssentialsHuddleSpaceRoom CurrentRoom
{
get { return _currentRoom; }
get { return _CurrentRoom; }
set
{
SetCurrentRoom(value);
}
}
EssentialsHuddleSpaceRoom _currentRoom;
EssentialsHuddleSpaceRoom _CurrentRoom;
/// <summary>
///
@@ -82,86 +93,88 @@ namespace PepperDash.Essentials
/// <summary>
/// For hitting feedback
/// </summary>
private readonly BoolInputSig _shareButtonSig;
private BoolInputSig _endMeetingButtonSig;
BoolInputSig ShareButtonSig;
BoolInputSig EndMeetingButtonSig;
/// <summary>
/// Controls the extended period that the volume gauge shows on-screen,
/// as triggered by Volume up/down operations
/// </summary>
private readonly BoolFeedbackPulseExtender _volumeGaugeFeedback;
BoolFeedbackPulseExtender VolumeGaugeFeedback;
/// <summary>
/// Controls the period that the volume buttons show on non-hard-button
/// interfaces
/// </summary>
private readonly BoolFeedbackPulseExtender _volumeButtonsPopupFeedback;
BoolFeedbackPulseExtender VolumeButtonsPopupFeedback;
/// <summary>
/// The parent driver for this
/// </summary>
private readonly PanelDriverBase _parent;
PanelDriverBase Parent;
/// <summary>
/// All children attached to this driver. For hiding and showing as a group.
/// </summary>
private List<PanelDriverBase> _childDrivers = new List<PanelDriverBase>();
List<PanelDriverBase> ChildDrivers = new List<PanelDriverBase>();
private readonly List<BoolInputSig> _currentDisplayModeSigsInUse = new List<BoolInputSig>();
List<BoolInputSig> CurrentDisplayModeSigsInUse = new List<BoolInputSig>();
//// Important smart objects
/// <summary>
/// Smart Object 3200
/// </summary>
private readonly SubpageReferenceList _sourcesSrl;
SubpageReferenceList SourcesSrl;
/// <summary>
/// Smart Object 15022
/// </summary>
private readonly SubpageReferenceList _activityFooterSrl;
SubpageReferenceList ActivityFooterSrl;
/// <summary>
/// Tracks which audio page group the UI is in
/// </summary>
private UiDisplayMode _currentDisplayMode;
UiDisplayMode CurrentDisplayMode;
/// <summary>
/// The AV page mangagers that have been used, to keep them alive for later
/// </summary>
private readonly Dictionary<object, PageManager> _pageManagers = new Dictionary<object, PageManager>();
Dictionary<object, PageManager> PageManagers = new Dictionary<object, PageManager>();
/// <summary>
/// Current page manager running for a source
/// </summary>
private PageManager _currentSourcePageManager;
PageManager CurrentSourcePageManager;
/// <summary>
/// Will auto-timeout a power off
/// </summary>
private CTimer _powerOffTimer;
CTimer PowerOffTimer;
private ModalDialog _powerDownModal;
ModalDialog PowerDownModal;
public JoinedSigInterlock PopupInterlock { get; private set; }
/// <summary>
/// The driver for the tech page. Lazy getter for memory usage
/// </summary>
EssentialsHuddleTechPageDriver TechDriver
PepperDash.Essentials.UIDrivers.EssentialsHuddleTechPageDriver TechDriver
{
get {
return _techDriver ??
(_techDriver = new EssentialsHuddleTechPageDriver(TriList, CurrentRoom.PropertiesConfig.Tech));
get
{
if (_TechDriver == null)
_TechDriver = new PepperDash.Essentials.UIDrivers.EssentialsHuddleTechPageDriver(TriList, CurrentRoom.PropertiesConfig.Tech);
return _TechDriver;
}
}
private EssentialsHuddleTechPageDriver _techDriver;
PepperDash.Essentials.UIDrivers.EssentialsHuddleTechPageDriver _TechDriver;
/// <summary>
/// Controls timeout of notification ribbon timer
/// </summary>
private CTimer _ribbonTimer;
CTimer RibbonTimer;
/// <summary>
/// Constructor
@@ -169,25 +182,25 @@ namespace PepperDash.Essentials
public EssentialsHuddlePanelAvFunctionsDriver(PanelDriverBase parent, CrestronTouchpanelPropertiesConfig config)
: base(parent.TriList)
{
_config = config;
_parent = parent;
Config = config;
Parent = parent;
PopupInterlock = new JoinedSigInterlock(TriList);
_sourcesSrl = new SubpageReferenceList(TriList, 3200, 3, 3, 3);
_activityFooterSrl = new SubpageReferenceList(TriList, 15022, 3, 3, 3);
_shareButtonSig = _activityFooterSrl.BoolInputSig(1, 1);
SourcesSrl = new SubpageReferenceList(TriList, 3200, 3, 3, 3);
ActivityFooterSrl = new SubpageReferenceList(TriList, 15022, 3, 3, 3);
ShareButtonSig = ActivityFooterSrl.BoolInputSig(1, 1);
SetupActivityFooterWhenRoomOff();
ShowVolumeGauge = true;
// One-second pulse extender for volume gauge
_volumeGaugeFeedback = new BoolFeedbackPulseExtender(1500);
_volumeGaugeFeedback.Feedback
VolumeGaugeFeedback = new BoolFeedbackPulseExtender(1500);
VolumeGaugeFeedback.Feedback
.LinkInputSig(TriList.BooleanInput[UIBoolJoin.VolumeGaugePopupVisible]);
_volumeButtonsPopupFeedback = new BoolFeedbackPulseExtender(4000);
_volumeButtonsPopupFeedback.Feedback
VolumeButtonsPopupFeedback = new BoolFeedbackPulseExtender(4000);
VolumeButtonsPopupFeedback.Feedback
.LinkInputSig(TriList.BooleanInput[UIBoolJoin.VolumeButtonPopupVisible]);
PowerOffTimeout = 30000;
@@ -207,19 +220,30 @@ namespace PepperDash.Essentials
return;
}
switch (_config.HeaderStyle.ToLower())
{
case CrestronTouchpanelPropertiesConfig.Habanero:
TriList.SetSigFalseAction(UIBoolJoin.HeaderRoomButtonPress, () =>
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderPageVisible));
break;
case CrestronTouchpanelPropertiesConfig.Verbose:
break;
}
var roomConf = CurrentRoom.PropertiesConfig;
TriList.SetBool(UIBoolJoin.DateAndTimeVisible, _config.ShowDate && _config.ShowTime);
TriList.SetBool(UIBoolJoin.DateOnlyVisible, _config.ShowDate && !_config.ShowTime);
TriList.SetBool(UIBoolJoin.TimeOnlyVisible, !_config.ShowDate && _config.ShowTime);
if (Config.HeaderStyle.ToLower() == CrestronTouchpanelPropertiesConfig.Habanero)
{
TriList.SetSigFalseAction(UIBoolJoin.HeaderRoomButtonPress, () =>
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderPageVisible));
}
else if (Config.HeaderStyle.ToLower() == CrestronTouchpanelPropertiesConfig.Verbose)
{
// room name on join 1, concat phone and sip on join 2, no button method
//var addr = roomConf.Addresses;
//if (addr == null) // protect from missing values by using default empties
// addr = new EssentialsRoomAddressPropertiesConfig();
//// empty string when either missing, pipe when both showing
//TriList.SetString(UIStringJoin.RoomAddressPipeText,
// (string.IsNullOrEmpty(addr.PhoneNumber.Trim())
// || string.IsNullOrEmpty(addr.SipAddress.Trim())) ? "" : " | ");
//TriList.SetString(UIStringJoin.RoomPhoneText, addr.PhoneNumber);
//TriList.SetString(UIStringJoin.RoomSipText, addr.SipAddress);
}
TriList.SetBool(UIBoolJoin.DateAndTimeVisible, Config.ShowDate && Config.ShowTime);
TriList.SetBool(UIBoolJoin.DateOnlyVisible, Config.ShowDate && !Config.ShowTime);
TriList.SetBool(UIBoolJoin.TimeOnlyVisible, !Config.ShowDate && Config.ShowTime);
TriList.SetBool(UIBoolJoin.TopBarHabaneroDynamicVisible, true);
TriList.BooleanInput[UIBoolJoin.ActivityFooterVisible].BoolValue = true;
@@ -306,7 +330,7 @@ namespace PepperDash.Essentials
{
TriList.SetBool(UIBoolJoin.LogoDefaultVisible, false);
TriList.SetBool(UIBoolJoin.LogoUrlVisible, true);
TriList.SetString(UIStringJoin.LogoUrl, _currentRoom.LogoUrl);
TriList.SetString(UIStringJoin.LogoUrl, _CurrentRoom.LogoUrl);
}
}
@@ -331,7 +355,7 @@ namespace PepperDash.Essentials
TriList.BooleanInput[UIBoolJoin.TapToBeginVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
//TriList.BooleanInput[UIBoolJoin.StagingPageVisible].BoolValue = false;
_volumeButtonsPopupFeedback.ClearNow();
VolumeButtonsPopupFeedback.ClearNow();
//CancelPowerOff();
base.Hide();
@@ -348,12 +372,12 @@ namespace PepperDash.Essentials
TriList.SetBool(UIBoolJoin.NotificationRibbonVisible, true);
if (timeout > 0)
{
if (_ribbonTimer != null)
_ribbonTimer.Stop();
_ribbonTimer = new CTimer(o =>
if (RibbonTimer != null)
RibbonTimer.Stop();
RibbonTimer = new CTimer(o =>
{
TriList.SetBool(UIBoolJoin.NotificationRibbonVisible, false);
_ribbonTimer = null;
RibbonTimer = null;
}, timeout);
}
}
@@ -364,10 +388,10 @@ namespace PepperDash.Essentials
public void HideNotificationRibbon()
{
TriList.SetBool(UIBoolJoin.NotificationRibbonVisible, false);
if (_ribbonTimer != null)
if (RibbonTimer != null)
{
_ribbonTimer.Stop();
_ribbonTimer = null;
RibbonTimer.Stop();
RibbonTimer = null;
}
}
@@ -379,7 +403,7 @@ namespace PepperDash.Essentials
{
//Clear whatever is showing now.
HideAndClearCurrentDisplayModeSigsInUse();
_currentDisplayMode = mode;
CurrentDisplayMode = mode;
switch (mode)
{
case UiDisplayMode.PresentationMode:
@@ -397,7 +421,7 @@ namespace PepperDash.Essentials
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
}
// Date/time
if (_config.ShowDate && _config.ShowTime)
if (Config.ShowDate && Config.ShowTime)
{
TriList.BooleanInput[UIBoolJoin.DateAndTimeVisible].BoolValue = true;
TriList.BooleanInput[UIBoolJoin.DateOnlyVisible].BoolValue = false;
@@ -406,8 +430,8 @@ namespace PepperDash.Essentials
else
{
TriList.BooleanInput[UIBoolJoin.DateAndTimeVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.DateOnlyVisible].BoolValue = _config.ShowDate;
TriList.BooleanInput[UIBoolJoin.TimeOnlyVisible].BoolValue = _config.ShowTime;
TriList.BooleanInput[UIBoolJoin.DateOnlyVisible].BoolValue = Config.ShowDate;
TriList.BooleanInput[UIBoolJoin.TimeOnlyVisible].BoolValue = Config.ShowTime;
}
ShowCurrentDisplayModeSigsInUse();
@@ -420,12 +444,12 @@ namespace PepperDash.Essentials
/// </summary>
void SetupActivityFooterWhenRoomOff()
{
_activityFooterSrl.Clear();
_activityFooterSrl.AddItem(new SubpageReferenceListActivityItem(1, _activityFooterSrl, 0,
ActivityFooterSrl.Clear();
ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(1, ActivityFooterSrl, 0,
b => { if (!b) ShareButtonPressed(); }));
_activityFooterSrl.Count = 1;
ActivityFooterSrl.Count = 1;
TriList.UShortInput[UIUshortJoin.PresentationStagingCaretMode].UShortValue = 0;
_shareButtonSig.BoolValue = false;
ShareButtonSig.BoolValue = false;
}
/// <summary>
@@ -433,15 +457,15 @@ namespace PepperDash.Essentials
/// </summary>
void SetupActivityFooterWhenRoomOn()
{
_activityFooterSrl.Clear();
_activityFooterSrl.AddItem(new SubpageReferenceListActivityItem(1, _activityFooterSrl,
ActivityFooterSrl.Clear();
ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(1, ActivityFooterSrl,
0, null));
_activityFooterSrl.AddItem(new SubpageReferenceListActivityItem(2, _activityFooterSrl,
ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(2, ActivityFooterSrl,
4, b => { if (!b) PowerButtonPressed(); }));
_activityFooterSrl.Count = 2;
ActivityFooterSrl.Count = 2;
TriList.UShortInput[UIUshortJoin.PresentationStagingCaretMode].UShortValue = 1;
_endMeetingButtonSig = _activityFooterSrl.BoolInputSig(2, 1);
_shareButtonSig.BoolValue = CurrentRoom.OnFeedback.BoolValue;
EndMeetingButtonSig = ActivityFooterSrl.BoolInputSig(2, 1);
ShareButtonSig.BoolValue = CurrentRoom.OnFeedback.BoolValue;
}
/// <summary>
@@ -449,7 +473,7 @@ namespace PepperDash.Essentials
/// </summary>
void ShareButtonPressed()
{
_shareButtonSig.BoolValue = true;
ShareButtonSig.BoolValue = true;
TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = true;
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = true;
@@ -464,7 +488,7 @@ namespace PepperDash.Essentials
/// </summary>
void ShowCurrentDisplayModeSigsInUse()
{
foreach (var sig in _currentDisplayModeSigsInUse)
foreach (var sig in CurrentDisplayModeSigsInUse)
sig.BoolValue = true;
}
@@ -473,9 +497,9 @@ namespace PepperDash.Essentials
/// </summary>
void HideAndClearCurrentDisplayModeSigsInUse()
{
foreach (var sig in _currentDisplayModeSigsInUse)
foreach (var sig in CurrentDisplayModeSigsInUse)
sig.BoolValue = false;
_currentDisplayModeSigsInUse.Clear();
CurrentDisplayModeSigsInUse.Clear();
}
/// <summary>
@@ -483,7 +507,7 @@ namespace PepperDash.Essentials
/// </summary>
public override void BackButtonPressed()
{
switch (_currentDisplayMode)
switch (CurrentDisplayMode)
{
case UiDisplayMode.PresentationMode:
//CancelReturnToSourceTimer();
@@ -498,7 +522,7 @@ namespace PepperDash.Essentials
void BackToHome()
{
Hide();
_parent.Show();
Parent.Show();
}
/// <summary>
@@ -510,28 +534,26 @@ namespace PepperDash.Essentials
return;
var uiDev = CurrentRoom.CurrentSourceInfo.SourceDevice as IUiDisplayInfo;
// If we need a page manager, get an appropriate one
if (uiDev == null)
{
return;
}
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
// Got an existing page manager, get it
PageManager pm;
if (_pageManagers.ContainsKey(uiDev))
pm = _pageManagers[uiDev];
// Otherwise make an apporiate one
else if (uiDev is ISetTopBoxControls)
//pm = new SetTopBoxMediumPageManager(uiDev as ISetTopBoxControls, TriList);
pm = new SetTopBoxThreePanelPageManager(uiDev as ISetTopBoxControls, TriList);
else if (uiDev is IDiscPlayerControls)
pm = new DiscPlayerMediumPageManager(uiDev as IDiscPlayerControls, TriList);
else
pm = new DefaultPageManager(uiDev, TriList);
_pageManagers[uiDev] = pm;
_currentSourcePageManager = pm;
pm.Show();
PageManager pm = null;
// If we need a page manager, get an appropriate one
if (uiDev != null)
{
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
// Got an existing page manager, get it
if (PageManagers.ContainsKey(uiDev))
pm = PageManagers[uiDev];
// Otherwise make an apporiate one
else if (uiDev is ISetTopBoxControls)
//pm = new SetTopBoxMediumPageManager(uiDev as ISetTopBoxControls, TriList);
pm = new SetTopBoxThreePanelPageManager(uiDev as ISetTopBoxControls, TriList);
else if (uiDev is IDiscPlayerControls)
pm = new DiscPlayerMediumPageManager(uiDev as IDiscPlayerControls, TriList);
else
pm = new DefaultPageManager(uiDev, TriList);
PageManagers[uiDev] = pm;
CurrentSourcePageManager = pm;
pm.Show();
}
}
/// <summary>
@@ -542,7 +564,7 @@ namespace PepperDash.Essentials
void UiSelectSource(string key)
{
// Run the route and when it calls back, show the source
CurrentRoom.RunRouteAction(key, () => { });
CurrentRoom.RunRouteAction(key, new Action(() => { }));
}
/// <summary>
@@ -566,12 +588,12 @@ namespace PepperDash.Essentials
{
// Do we need to check where the UI is? No?
var timer = CurrentRoom.ShutdownPromptTimer;
_endMeetingButtonSig.BoolValue = true;
_shareButtonSig.BoolValue = false;
EndMeetingButtonSig.BoolValue = true;
ShareButtonSig.BoolValue = false;
if (CurrentRoom.ShutdownType == eShutdownType.Manual || CurrentRoom.ShutdownType == eShutdownType.Vacancy)
{
_powerDownModal = new ModalDialog(TriList);
PowerDownModal = new ModalDialog(TriList);
var message = string.Format("Meeting will end in {0} seconds", CurrentRoom.ShutdownPromptSeconds);
// Attach timer things to modal
@@ -585,15 +607,15 @@ namespace PepperDash.Essentials
{
if (!onFb.BoolValue)
{
_endMeetingButtonSig.BoolValue = false;
_powerDownModal.HideDialog();
EndMeetingButtonSig.BoolValue = false;
PowerDownModal.HideDialog();
onFb.OutputChange -= offHandler;
//gauge.OutputChange -= gaugeHandler;
}
};
onFb.OutputChange += offHandler;
_powerDownModal.PresentModalDialog(2, "End Meeting", "Power", message, "Cancel", "End Meeting Now", true, true,
PowerDownModal.PresentModalDialog(2, "End Meeting", "Power", message, "Cancel", "End Meeting Now", true, true,
but =>
{
if (but != 2) // any button except for End cancels
@@ -611,7 +633,7 @@ namespace PepperDash.Essentials
/// <param name="e"></param>
void ShutdownPromptTimer_HasFinished(object sender, EventArgs e)
{
_endMeetingButtonSig.BoolValue = false;
EndMeetingButtonSig.BoolValue = false;
CurrentRoom.ShutdownPromptTimer.TimeRemainingFeedback.OutputChange -= ShutdownPromptTimer_TimeRemainingFeedback_OutputChange;
CurrentRoom.ShutdownPromptTimer.PercentFeedback.OutputChange -= ShutdownPromptTimer_PercentFeedback_OutputChange;
}
@@ -623,10 +645,10 @@ namespace PepperDash.Essentials
/// <param name="e"></param>
void ShutdownPromptTimer_WasCancelled(object sender, EventArgs e)
{
if (_powerDownModal != null)
_powerDownModal.HideDialog();
_endMeetingButtonSig.BoolValue = false;
_shareButtonSig.BoolValue = CurrentRoom.OnFeedback.BoolValue;
if (PowerDownModal != null)
PowerDownModal.HideDialog();
EndMeetingButtonSig.BoolValue = false;
ShareButtonSig.BoolValue = CurrentRoom.OnFeedback.BoolValue;
CurrentRoom.ShutdownPromptTimer.TimeRemainingFeedback.OutputChange += ShutdownPromptTimer_TimeRemainingFeedback_OutputChange;
CurrentRoom.ShutdownPromptTimer.PercentFeedback.OutputChange -= ShutdownPromptTimer_PercentFeedback_OutputChange;
@@ -634,38 +656,27 @@ namespace PepperDash.Essentials
void ShutdownPromptTimer_TimeRemainingFeedback_OutputChange(object sender, EventArgs e)
{
var stringFeedback = sender as StringFeedback;
if (stringFeedback == null)
{
return;
}
var message = string.Format("Meeting will end in {0} seconds", stringFeedback.StringValue);
var message = string.Format("Meeting will end in {0} seconds", (sender as StringFeedback).StringValue);
TriList.StringInput[ModalDialog.MessageTextJoin].StringValue = message;
}
void ShutdownPromptTimer_PercentFeedback_OutputChange(object sender, EventArgs e)
{
var intFeedback = sender as IntFeedback;
if (intFeedback == null)
{
return;
}
var value = (ushort)(intFeedback.UShortValue * 65535 / 100);
TriList.UShortInput[ModalDialog.TimerGaugeJoin].UShortValue = value;
}
void ShutdownPromptTimer_PercentFeedback_OutputChange(object sender, EventArgs e)
{
var value = (ushort)((sender as IntFeedback).UShortValue * 65535 / 100);
TriList.UShortInput[ModalDialog.TimerGaugeJoin].UShortValue = value;
}
/// <summary>
/// <summary>
///
/// </summary>
void CancelPowerOffTimer()
{
if (_powerOffTimer == null)
{
return;
}
_powerOffTimer.Stop();
_powerOffTimer = null;
if (PowerOffTimer != null)
{
PowerOffTimer.Stop();
PowerOffTimer = null;
}
}
/// <summary>
@@ -673,13 +684,13 @@ namespace PepperDash.Essentials
/// </summary>
void VolumeButtonsTogglePress()
{
if (_volumeButtonsPopupFeedback.BoolValue)
_volumeButtonsPopupFeedback.ClearNow();
if (VolumeButtonsPopupFeedback.BoolValue)
VolumeButtonsPopupFeedback.ClearNow();
else
{
// Trigger the popup
_volumeButtonsPopupFeedback.BoolValue = true;
_volumeButtonsPopupFeedback.BoolValue = false;
VolumeButtonsPopupFeedback.BoolValue = true;
VolumeButtonsPopupFeedback.BoolValue = false;
}
}
@@ -691,8 +702,8 @@ namespace PepperDash.Essentials
{
// extend timeouts
if (ShowVolumeGauge)
_volumeGaugeFeedback.BoolValue = state;
_volumeButtonsPopupFeedback.BoolValue = state;
VolumeGaugeFeedback.BoolValue = state;
VolumeButtonsPopupFeedback.BoolValue = state;
if (CurrentRoom.CurrentVolumeControls != null)
CurrentRoom.CurrentVolumeControls.VolumeUp(state);
}
@@ -705,8 +716,8 @@ namespace PepperDash.Essentials
{
// extend timeouts
if (ShowVolumeGauge)
_volumeGaugeFeedback.BoolValue = state;
_volumeButtonsPopupFeedback.BoolValue = state;
VolumeGaugeFeedback.BoolValue = state;
VolumeButtonsPopupFeedback.BoolValue = state;
if (CurrentRoom.CurrentVolumeControls != null)
CurrentRoom.CurrentVolumeControls.VolumeDown(state);
}
@@ -717,31 +728,31 @@ namespace PepperDash.Essentials
/// </summary>
public void RefreshCurrentRoom(EssentialsHuddleSpaceRoom room)
{
if (_currentRoom != null)
if (_CurrentRoom != null)
{
// Disconnect current room
_currentRoom.CurrentVolumeDeviceChange -= CurrentRoom_CurrentAudioDeviceChange;
_CurrentRoom.CurrentVolumeDeviceChange -= this.CurrentRoom_CurrentAudioDeviceChange;
ClearAudioDeviceConnections();
_currentRoom.CurrentSourceChange -= CurrentRoom_SourceInfoChange;
DisconnectSource(_currentRoom.CurrentSourceInfo);
_currentRoom.ShutdownPromptTimer.HasStarted -= ShutdownPromptTimer_HasStarted;
_currentRoom.ShutdownPromptTimer.HasFinished -= ShutdownPromptTimer_HasFinished;
_currentRoom.ShutdownPromptTimer.WasCancelled -= ShutdownPromptTimer_WasCancelled;
_CurrentRoom.CurrentSourceChange -= this.CurrentRoom_SourceInfoChange;
DisconnectSource(_CurrentRoom.CurrentSourceInfo);
_CurrentRoom.ShutdownPromptTimer.HasStarted -= ShutdownPromptTimer_HasStarted;
_CurrentRoom.ShutdownPromptTimer.HasFinished -= ShutdownPromptTimer_HasFinished;
_CurrentRoom.ShutdownPromptTimer.WasCancelled -= ShutdownPromptTimer_WasCancelled;
_currentRoom.OnFeedback.OutputChange -= CurrentRoom_OnFeedback_OutputChange;
_currentRoom.IsWarmingUpFeedback.OutputChange -= CurrentRoom_IsWarmingFeedback_OutputChange;
_currentRoom.IsCoolingDownFeedback.OutputChange -= IsCoolingDownFeedback_OutputChange;
_CurrentRoom.OnFeedback.OutputChange -= CurrentRoom_OnFeedback_OutputChange;
_CurrentRoom.IsWarmingUpFeedback.OutputChange -= CurrentRoom_IsWarmingFeedback_OutputChange;
_CurrentRoom.IsCoolingDownFeedback.OutputChange -= IsCoolingDownFeedback_OutputChange;
}
_currentRoom = room;
_CurrentRoom = room;
if (_currentRoom != null)
if (_CurrentRoom != null)
{
// get the source list config and set up the source list
var config = ConfigReader.ConfigObject.SourceLists;
if (config.ContainsKey(_currentRoom.SourceListKey))
if (config.ContainsKey(_CurrentRoom.SourceListKey))
{
var srcList = config[_currentRoom.SourceListKey];
var srcList = config[_CurrentRoom.SourceListKey];
// Setup sources list
uint i = 1; // counter for UI list
foreach (var kvp in srcList)
@@ -758,16 +769,16 @@ namespace PepperDash.Essentials
continue;
}
var routeKey = kvp.Key;
var item = new SubpageReferenceListSourceItem(i++, _sourcesSrl, srcConfig,
var item = new SubpageReferenceListSourceItem(i++, SourcesSrl, srcConfig,
b => { if (!b) UiSelectSource(routeKey); });
_sourcesSrl.AddItem(item); // add to the SRL
item.RegisterForSourceChange(_currentRoom);
SourcesSrl.AddItem(item); // add to the SRL
item.RegisterForSourceChange(_CurrentRoom);
}
_sourcesSrl.Count = (ushort)(i - 1);
SourcesSrl.Count = (ushort)(i - 1);
}
// Name and logo
TriList.StringInput[UIStringJoin.CurrentRoomName].StringValue = _currentRoom.Name;
if (_currentRoom.LogoUrl == null)
TriList.StringInput[UIStringJoin.CurrentRoomName].StringValue = _CurrentRoom.Name;
if (_CurrentRoom.LogoUrl == null)
{
TriList.BooleanInput[UIBoolJoin.LogoDefaultVisible].BoolValue = true;
TriList.BooleanInput[UIBoolJoin.LogoUrlVisible].BoolValue = false;
@@ -776,31 +787,26 @@ namespace PepperDash.Essentials
{
TriList.BooleanInput[UIBoolJoin.LogoDefaultVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.LogoUrlVisible].BoolValue = true;
TriList.StringInput[UIStringJoin.LogoUrl].StringValue = _currentRoom.LogoUrl;
TriList.StringInput[UIStringJoin.LogoUrl].StringValue = _CurrentRoom.LogoUrl;
}
// Shutdown timer
_currentRoom.ShutdownPromptTimer.HasStarted += ShutdownPromptTimer_HasStarted;
_currentRoom.ShutdownPromptTimer.HasFinished += ShutdownPromptTimer_HasFinished;
_currentRoom.ShutdownPromptTimer.WasCancelled += ShutdownPromptTimer_WasCancelled;
_CurrentRoom.ShutdownPromptTimer.HasStarted += ShutdownPromptTimer_HasStarted;
_CurrentRoom.ShutdownPromptTimer.HasFinished += ShutdownPromptTimer_HasFinished;
_CurrentRoom.ShutdownPromptTimer.WasCancelled += ShutdownPromptTimer_WasCancelled;
// Link up all the change events from the room
_currentRoom.OnFeedback.OutputChange += CurrentRoom_OnFeedback_OutputChange;
_CurrentRoom.OnFeedback.OutputChange += CurrentRoom_OnFeedback_OutputChange;
CurrentRoom_SyncOnFeedback();
_currentRoom.IsWarmingUpFeedback.OutputChange += CurrentRoom_IsWarmingFeedback_OutputChange;
_currentRoom.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange;
_CurrentRoom.IsWarmingUpFeedback.OutputChange += CurrentRoom_IsWarmingFeedback_OutputChange;
_CurrentRoom.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange;
_currentRoom.CurrentVolumeDeviceChange += CurrentRoom_CurrentAudioDeviceChange;
_CurrentRoom.CurrentVolumeDeviceChange += CurrentRoom_CurrentAudioDeviceChange;
RefreshAudioDeviceConnections();
_currentRoom.CurrentSourceChange += CurrentRoom_SourceInfoChange;
_CurrentRoom.CurrentSourceChange += CurrentRoom_SourceInfoChange;
RefreshSourceInfo();
var essentialsPanelMainInterfaceDriver = _parent as EssentialsPanelMainInterfaceDriver;
if (essentialsPanelMainInterfaceDriver != null)
{
essentialsPanelMainInterfaceDriver.HeaderDriver.SetupHeaderButtons(this, CurrentRoom);
}
(Parent as EssentialsPanelMainInterfaceDriver).HeaderDriver.SetupHeaderButtons(this, CurrentRoom);
}
else
{
@@ -811,7 +817,7 @@ namespace PepperDash.Essentials
void SetCurrentRoom(EssentialsHuddleSpaceRoom room)
{
if (_currentRoom == room) return;
if (_CurrentRoom == room) return;
// Disconnect current (probably never called)
room.ConfigChanged -= room_ConfigChanged;
@@ -827,7 +833,7 @@ namespace PepperDash.Essentials
/// <param name="e"></param>
void room_ConfigChanged(object sender, EventArgs e)
{
RefreshCurrentRoom(_currentRoom);
RefreshCurrentRoom(_CurrentRoom);
}
/// <summary>
@@ -840,7 +846,7 @@ namespace PepperDash.Essentials
void CurrentRoom_SyncOnFeedback()
{
var value = _currentRoom.OnFeedback.BoolValue;
var value = _CurrentRoom.OnFeedback.BoolValue;
//Debug.Console(2, CurrentRoom, "UI: Is on event={0}", value);
TriList.BooleanInput[UIBoolJoin.RoomIsOn].BoolValue = value;
@@ -902,14 +908,15 @@ namespace PepperDash.Essentials
// Hide whatever is showing
if (IsVisible)
{
if (_currentSourcePageManager != null)
if (CurrentSourcePageManager != null)
{
_currentSourcePageManager.Hide();
_currentSourcePageManager = null;
CurrentSourcePageManager.Hide();
CurrentSourcePageManager = null;
}
}
var previousDev = previousInfo.SourceDevice;
if (previousInfo == null) return;
var previousDev = previousInfo.SourceDevice;
// device type interfaces
if (previousDev is ISetTopBoxControls)
@@ -940,7 +947,7 @@ namespace PepperDash.Essentials
{
var routeInfo = CurrentRoom.CurrentSourceInfo;
// This will show off popup too
if (IsVisible)
if (this.IsVisible)
ShowCurrentSource();
if (routeInfo == null)// || !CurrentRoom.OnFeedback.BoolValue)
@@ -948,23 +955,22 @@ namespace PepperDash.Essentials
// Check for power off and insert "Room is off"
TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = "Room is off";
TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = "Power";
Hide();
_parent.Show();
this.Hide();
Parent.Show();
return;
}
if (CurrentRoom.CurrentSourceInfo != null)
{
TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = routeInfo.PreferredName;
TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = routeInfo.Icon; // defaults to "blank"
}
else
{
TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = "---";
TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = "Blank";
}
// Connect controls
else if (CurrentRoom.CurrentSourceInfo != null)
{
TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = routeInfo.PreferredName;
TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = routeInfo.Icon; // defaults to "blank"
}
else
{
TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = "---";
TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = "Blank";
}
// Connect controls
if (routeInfo.SourceDevice != null)
ConnectControlDeviceMethods(routeInfo.SourceDevice);
}

View File

@@ -13,7 +13,7 @@ using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.Touchpanels.Keyboards;
using PepperDash.Essentials.Devices.Displays;
using PepperDash.Essentials.Core.Rooms.Config;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.UIDrivers
{

View File

@@ -8,11 +8,10 @@ using Crestron.SimplSharpPro.UI;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Devices.VideoCodec;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.PageManagers;
using PepperDash.Essentials.Core.Rooms.Config;
using PepperDash.Essentials.Core.Devices.Codec;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
namespace PepperDash.Essentials

View File

@@ -9,12 +9,10 @@ using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Devices.VideoCodec;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.Touchpanels.Keyboards;
using PepperDash.Essentials.Core.Devices.Codec;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Core.VideoCodec;
namespace PepperDash.Essentials.UIDrivers.VC
{

View File

@@ -96,8 +96,6 @@ namespace PepperDash.Essentials.Core.Bridges
Eisc.SigChange += Eisc_SigChange;
Eisc.Register();
AddPostActivationAction( () =>
{
Debug.Console(1, this, "Linking Devices...");
@@ -121,6 +119,16 @@ namespace PepperDash.Essentials.Core.Bridges
var bridge = device as IBridgeAdvanced;
if (bridge != null) bridge.LinkToApi(Eisc, d.JoinStart, d.JoinMapKey, this);
}
var registerResult = Eisc.Register();
if (registerResult != eDeviceRegistrationUnRegistrationResponse.Success)
{
Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Registration result: {0}", registerResult);
return;
}
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "EISC registration successful");
});
}
@@ -190,11 +198,11 @@ namespace PepperDash.Essentials.Core.Bridges
var uo = Eisc.BooleanOutput[join].UserObject as Action<bool>;
if (uo != null)
{
Debug.Console(1, this, "Executing Action: {0}", uo.ToString());
Debug.Console(2, this, "Executing Action: {0}", uo.ToString());
uo(Convert.ToBoolean(state));
}
else
Debug.Console(1, this, "User Action is null. Nothing to Execute");
Debug.Console(2, this, "User Action is null. Nothing to Execute");
break;
}
case "analog":
@@ -202,27 +210,27 @@ namespace PepperDash.Essentials.Core.Bridges
var uo = Eisc.BooleanOutput[join].UserObject as Action<ushort>;
if (uo != null)
{
Debug.Console(1, this, "Executing Action: {0}", uo.ToString());
Debug.Console(2, this, "Executing Action: {0}", uo.ToString());
uo(Convert.ToUInt16(state));
}
else
Debug.Console(1, this, "User Action is null. Nothing to Execute"); break;
Debug.Console(2, this, "User Action is null. Nothing to Execute"); break;
}
case "serial":
{
var uo = Eisc.BooleanOutput[join].UserObject as Action<string>;
if (uo != null)
{
Debug.Console(1, this, "Executing Action: {0}", uo.ToString());
Debug.Console(2, this, "Executing Action: {0}", uo.ToString());
uo(Convert.ToString(state));
}
else
Debug.Console(1, this, "User Action is null. Nothing to Execute");
Debug.Console(2, this, "User Action is null. Nothing to Execute");
break;
}
default:
{
Debug.Console(1, "Unknown join type. Use digital/serial/analog");
Debug.Console(2, "Unknown join type. Use digital/serial/analog");
break;
}
}

View File

@@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash_Essentials_Core.Bridges.JoinMaps
{
public class GlsPartitionSensorJoinMap : JoinMapBaseAdvanced
{
[JoinName("IsOnline")]
public JoinDataComplete IsOnline = new JoinDataComplete(
new JoinData()
{
JoinNumber = 1,
JoinSpan = 1
},
new JoinMetadata()
{
Description = "Sensor Is Online",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("Name")]
public JoinDataComplete Name = new JoinDataComplete(
new JoinData()
{
JoinNumber = 1,
JoinSpan = 1
},
new JoinMetadata()
{
Description = "Sensor Name",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("Enable")]
public JoinDataComplete Enable = new JoinDataComplete(
new JoinData()
{
JoinNumber = 2,
JoinSpan = 1
},
new JoinMetadata()
{
Description = "Sensor Enable",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("PartitionSensed")]
public JoinDataComplete PartitionSensed = new JoinDataComplete(
new JoinData()
{
JoinNumber = 3,
JoinSpan = 1
},
new JoinMetadata()
{
Description = "Sensor Partition Sensed",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("PartitionNotSensed")]
public JoinDataComplete PartitionNotSensed = new JoinDataComplete(
new JoinData()
{
JoinNumber = 4,
JoinSpan = 1
},
new JoinMetadata()
{
Description = "Sensor Partition Not Sensed",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("IncreaseSensitivity")]
public JoinDataComplete IncreaseSensitivity = new JoinDataComplete(
new JoinData()
{
JoinNumber = 6,
JoinSpan = 1
},
new JoinMetadata()
{
Description = "Sensor Increase Sensitivity",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DecreaseSensitivity")]
public JoinDataComplete DecreaseSensitivity = new JoinDataComplete(
new JoinData()
{
JoinNumber = 7,
JoinSpan = 1
},
new JoinMetadata()
{
Description = "Sensor Decrease Sensitivity",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("Sensitivity")]
public JoinDataComplete Sensitivity = new JoinDataComplete(
new JoinData()
{
JoinNumber = 2,
JoinSpan = 1
},
new JoinMetadata()
{
Description = "Sensor Sensitivity",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Analog
});
public GlsPartitionSensorJoinMap(uint joinStart)
: base(joinStart, typeof (GlsPartitionSensorJoinMap))
{
}
}
}

View File

@@ -6,7 +6,6 @@ using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash_Essentials_Core.Devices;
namespace PepperDash.Essentials.Core.Config
{
@@ -24,10 +23,7 @@ namespace PepperDash.Essentials.Core.Config
[JsonProperty("sourceLists")]
public Dictionary<string, Dictionary<string, SourceListItem>> SourceLists { get; set; }
[JsonProperty("destinationLists")]
public Dictionary<string, Dictionary<string, DestinationListItem>> DestinationLists { get; set; }
[JsonProperty("tieLines")]
[JsonProperty("tieLines")]
public List<TieLineConfig> TieLines { get; set; }
[JsonProperty("joinMaps")]
@@ -44,14 +40,6 @@ namespace PepperDash.Essentials.Core.Config
return SourceLists[key];
}
public Dictionary<string, DestinationListItem> GetDestinationListForKey(string key)
{
if (string.IsNullOrEmpty(key) || !SourceLists.ContainsKey(key))
return null;
return DestinationLists[key];
}
/// <summary>
/// Checks Devices for an item with a Key that matches and returns it if found. Otherwise, retunes null
/// </summary>
@@ -64,9 +52,12 @@ namespace PepperDash.Essentials.Core.Config
var deviceConfig = Devices.FirstOrDefault(d => d.Key.Equals(key));
//removed if statement that was here...
//DeviceConfig will be null if it's not found in the list
return deviceConfig;
if (deviceConfig != null)
return deviceConfig;
else
{
return null;
}
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.GeneralIO;
@@ -13,21 +14,30 @@ namespace PepperDash.Essentials.Core.CrestronIO
[Description("Wrapper class for the C2N-RTHS sensor")]
public class C2nRthsController : CrestronGenericBridgeableBaseDevice
{
private readonly C2nRths _device;
private C2nRths _device;
public IntFeedback TemperatureFeedback { get; private set; }
public IntFeedback HumidityFeedback { get; private set; }
public C2nRthsController(string key, string name, GenericBase hardware) : base(key, name, hardware)
public C2nRthsController(string key, Func<DeviceConfig, C2nRths> preActivationFunc,
DeviceConfig config)
: base(key, config.Name)
{
_device = hardware as C2nRths;
TemperatureFeedback = new IntFeedback(() => _device.TemperatureFeedback.UShortValue);
HumidityFeedback = new IntFeedback(() => _device.HumidityFeedback.UShortValue);
AddPreActivationAction(() =>
{
_device = preActivationFunc(config);
if (_device != null) _device.BaseEvent += DeviceOnBaseEvent;
RegisterCrestronGenericBase(_device);
TemperatureFeedback = new IntFeedback(() => _device.TemperatureFeedback.UShortValue);
HumidityFeedback = new IntFeedback(() => _device.HumidityFeedback.UShortValue);
if (_device != null) _device.BaseEvent += DeviceOnBaseEvent;
});
}
private void DeviceOnBaseEvent(GenericBase device, BaseEventArgs args)
{
switch (args.EventId)
@@ -76,24 +86,63 @@ namespace PepperDash.Essentials.Core.CrestronIO
HumidityFeedback.LinkInputSig(trilist.UShortInput[joinMap.Humidity.JoinNumber]);
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = Name;
}
}
public class C2nRthsControllerFactory : EssentialsDeviceFactory<C2nRthsController>
{
public C2nRthsControllerFactory()
{
TypeNames = new List<string>() { "c2nrths" };
trilist.OnlineStatusChange += (d, args) =>
{
if (!args.DeviceOnLine) return;
UpdateFeedbacksWhenOnline();
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = Name;
};
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
private void UpdateFeedbacksWhenOnline()
{
Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device");
IsOnline.FireUpdate();
TemperatureFeedback.FireUpdate();
HumidityFeedback.FireUpdate();
}
#region PreActivation
private static C2nRths GetC2nRthsDevice(DeviceConfig dc)
{
var control = CommFactory.GetControlPropertiesConfig(dc);
var cresnetId = control.CresnetIdInt;
var branchId = control.ControlPortNumber;
var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey;
return new C2nRthsController(dc.Key, dc.Name, new C2nRths(cresnetId, Global.ControlSystem));
if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase))
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new C2nRths", parentKey);
return new C2nRths(cresnetId, Global.ControlSystem);
}
var cresnetBridge = DeviceManager.GetDeviceForKey(parentKey) as IHasCresnetBranches;
if (cresnetBridge != null)
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new C2nRths", parentKey);
return new C2nRths(cresnetId, cresnetBridge.CresnetBranches[branchId]);
}
Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey);
return null;
}
#endregion
public class C2nRthsControllerFactory : EssentialsDeviceFactory<C2nRthsController>
{
public C2nRthsControllerFactory()
{
TypeNames = new List<string>() { "c2nrths" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device");
return new C2nRthsController(dc.Key, GetC2nRthsDevice, dc);
}
}
}
}

View File

@@ -0,0 +1,51 @@
using System.Collections.Generic;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.GeneralIO;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core
{
public class DinCenCn2Controller : CrestronGenericBaseDevice, IHasCresnetBranches
{
private readonly DinCenCn2 _device;
public CrestronCollection<CresnetBranch> CresnetBranches
{
get {
return _device != null ? _device.Branches : null;
}
}
public DinCenCn2Controller(string key, string name, DinCenCn2 device, DeviceConfig config)
: base(key, name, device)
{
_device = device;
}
public class DinCenCn2ControllerFactory : EssentialsDeviceFactory<DinCenCn2Controller>
{
public DinCenCn2ControllerFactory()
{
TypeNames = new List<string>() { "dincencn2", "dincencn2poe", "din-cencn2", "din-cencn2-poe" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device");
var control = CommFactory.GetControlPropertiesConfig(dc);
var ipid = control.IpIdInt;
if (dc.Type.ToLower().Contains("poe"))
{
return new DinCenCn2Controller(dc.Key, dc.Name, new DinCenCn2Poe(ipid, Global.ControlSystem), dc);
}
return new DinCenCn2Controller(dc.Key, dc.Name, new DinCenCn2(ipid, Global.ControlSystem), dc);
}
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
namespace PepperDash.Essentials.Core
{
public interface IHasCresnetBranches
{
CrestronCollection<CresnetBranch> CresnetBranches { get; }
}
}

View File

@@ -31,13 +31,14 @@ namespace PepperDash.Essentials.Core.CrestronIO
RelayOutput = relay;
RelayOutput.Register();
RelayOutput.StateChange += new RelayEventHandler(RelayOutput_StateChange);
RelayOutput.StateChange += RelayOutput_StateChange;
}
public GenericRelayDevice(string key, string name, Func<IOPortConfig, Relay> postActivationFunc,
IOPortConfig config)
: base(key, name)
{
OutputIsOnFeedback = new BoolFeedback(() => RelayOutput.State);
AddPostActivationAction(() =>
{
@@ -46,7 +47,6 @@ namespace PepperDash.Essentials.Core.CrestronIO
RelayOutput.Register();
RelayOutput.StateChange += RelayOutput_StateChange;
});
}

View File

@@ -13,7 +13,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
[Description("Wrapper class for the Crestron StatusSign device")]
public class StatusSignController : CrestronGenericBridgeableBaseDevice
{
private readonly StatusSign _device;
private StatusSign _device;
public BoolFeedback RedLedEnabledFeedback { get; private set; }
public BoolFeedback GreenLedEnabledFeedback { get; private set; }
@@ -23,34 +23,40 @@ namespace PepperDash.Essentials.Core.CrestronIO
public IntFeedback GreenLedBrightnessFeedback { get; private set; }
public IntFeedback BlueLedBrightnessFeedback { get; private set; }
public StatusSignController(string key, string name, GenericBase hardware) : base(key, name, hardware)
public StatusSignController(string key, Func<DeviceConfig, StatusSign> preActivationFunc, DeviceConfig config) : base(key, config.Name)
{
_device = hardware as StatusSign;
AddPreActivationAction(() =>
{
_device = preActivationFunc(config);
RedLedEnabledFeedback =
RegisterCrestronGenericBase(_device);
RedLedEnabledFeedback =
new BoolFeedback(
() =>
_device.Leds[(uint) StatusSign.Led.eLedColor.Red]
.ControlFeedback.BoolValue);
GreenLedEnabledFeedback =
new BoolFeedback(
() =>
_device.Leds[(uint) StatusSign.Led.eLedColor.Green]
.ControlFeedback.BoolValue);
BlueLedEnabledFeedback =
new BoolFeedback(
() =>
_device.Leds[(uint) StatusSign.Led.eLedColor.Blue]
_device.Leds[(uint)StatusSign.Led.eLedColor.Red]
.ControlFeedback.BoolValue);
GreenLedEnabledFeedback =
new BoolFeedback(
() =>
_device.Leds[(uint)StatusSign.Led.eLedColor.Green]
.ControlFeedback.BoolValue);
BlueLedEnabledFeedback =
new BoolFeedback(
() =>
_device.Leds[(uint)StatusSign.Led.eLedColor.Blue]
.ControlFeedback.BoolValue);
RedLedBrightnessFeedback =
new IntFeedback(() => (int) _device.Leds[(uint) StatusSign.Led.eLedColor.Red].BrightnessFeedback);
GreenLedBrightnessFeedback =
new IntFeedback(() => (int) _device.Leds[(uint) StatusSign.Led.eLedColor.Green].BrightnessFeedback);
BlueLedBrightnessFeedback =
new IntFeedback(() => (int) _device.Leds[(uint) StatusSign.Led.eLedColor.Blue].BrightnessFeedback);
RedLedBrightnessFeedback =
new IntFeedback(() => (int)_device.Leds[(uint)StatusSign.Led.eLedColor.Red].BrightnessFeedback);
GreenLedBrightnessFeedback =
new IntFeedback(() => (int)_device.Leds[(uint)StatusSign.Led.eLedColor.Green].BrightnessFeedback);
BlueLedBrightnessFeedback =
new IntFeedback(() => (int)_device.Leds[(uint)StatusSign.Led.eLedColor.Blue].BrightnessFeedback);
if (_device != null) _device.BaseEvent += _device_BaseEvent;
if (_device != null) _device.BaseEvent += _device_BaseEvent;
});
}
void _device_BaseEvent(GenericBase device, BaseEventArgs args)
@@ -167,23 +173,51 @@ namespace PepperDash.Essentials.Core.CrestronIO
device.SetColor(redBrightness, greenBrightness, blueBrightness);
}
}
public class StatusSignControllerFactory : EssentialsDeviceFactory<StatusSignController>
{
public StatusSignControllerFactory()
#region PreActivation
private static StatusSign GetStatusSignDevice(DeviceConfig dc)
{
TypeNames = new List<string>() { "statussign" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new StatusSign Device");
var control = CommFactory.GetControlPropertiesConfig(dc);
var cresnetId = control.CresnetIdInt;
var branchId = control.ControlPortNumber;
var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey;
return new StatusSignController(dc.Key, dc.Name, new StatusSign(cresnetId, Global.ControlSystem));
if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase))
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new StatusSign", parentKey);
return new StatusSign(cresnetId, Global.ControlSystem);
}
var cresnetBridge = DeviceManager.GetDeviceForKey(parentKey) as IHasCresnetBranches;
if (cresnetBridge != null)
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new StatusSign", parentKey);
return new StatusSign(cresnetId, cresnetBridge.CresnetBranches[branchId]);
}
Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey);
return null;
}
#endregion
public class StatusSignControllerFactory : EssentialsDeviceFactory<StatusSignController>
{
public StatusSignControllerFactory()
{
TypeNames = new List<string>() { "statussign" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new StatusSign Device");
var control = CommFactory.GetControlPropertiesConfig(dc);
var cresnetId = control.CresnetIdInt;
return new StatusSignController(dc.Key, GetStatusSignDevice, dc);
}
}
}
}

View File

@@ -1,7 +1,9 @@
using System.Linq;
using System;
using System.Linq;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Core.JsonStandardObjects;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Core
@@ -11,7 +13,7 @@ namespace PepperDash.Essentials.Core
/// </summary>
public abstract class CrestronGenericBaseDevice : EssentialsDevice, IOnline, IHasFeedback, ICommunicationMonitor, IUsageTracking
{
public virtual GenericBase Hardware { get; protected set; }
protected GenericBase Hardware;
/// <summary>
/// Returns a list containing the Outputs that we want to expose.
@@ -42,6 +44,24 @@ namespace PepperDash.Essentials.Core
CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, hardware, 120000, 300000);
}
protected CrestronGenericBaseDevice(string key, string name)
: base(key, name)
{
Feedbacks = new FeedbackCollection<Feedback>();
}
protected void RegisterCrestronGenericBase(GenericBase hardware)
{
Hardware = hardware;
IsOnline = new BoolFeedback("IsOnlineFeedback", () => Hardware.IsOnline);
IsRegistered = new BoolFeedback("IsRegistered", () => Hardware.Registered);
IpConnectionsText = new StringFeedback("IpConnectionsText", () => Hardware.ConnectedIpList != null ? string.Join(",", Hardware.ConnectedIpList.Select(cip => cip.DeviceIpAddress).ToArray()) : string.Empty);
AddToFeedbackList(IsOnline, IpConnectionsText);
CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, hardware, 120000, 300000);
}
/// <summary>
/// Make sure that overriding classes call this!
/// Registers the Crestron device, connects up to the base events, starts communication monitor
@@ -135,6 +155,11 @@ namespace PepperDash.Essentials.Core
{
}
protected CrestronGenericBridgeableBaseDevice(string key, string name)
: base(key, name)
{
}
public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge);
}

View File

@@ -1,62 +0,0 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace PepperDash.Essentials.Core.Devices.Codec
{
public class CodecActiveCallItem
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("number")]
public string Number { get; set; }
[JsonProperty("type")]
[JsonConverter(typeof(StringEnumConverter))]
public eCodecCallType Type { get; set; }
[JsonProperty("status")]
[JsonConverter(typeof(StringEnumConverter))]
public eCodecCallStatus Status { get; set; }
[JsonProperty("direction")]
[JsonConverter(typeof(StringEnumConverter))]
public eCodecCallDirection Direction { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
//public object CallMetaData { get; set; }
/// <summary>
/// Returns true when this call is any status other than
/// Unknown, Disconnected, Disconnecting
/// </summary>
[JsonProperty("isActiveCall")]
public bool IsActiveCall
{
get
{
return !(Status == eCodecCallStatus.Disconnected
|| Status == eCodecCallStatus.Disconnecting
|| Status == eCodecCallStatus.Idle
|| Status == eCodecCallStatus.Unknown);
}
}
}
/// <summary>
///
/// </summary>
public class CodecCallStatusItemChangeEventArgs : EventArgs
{
public CodecActiveCallItem CallItem { get; private set; }
public CodecCallStatusItemChangeEventArgs(CodecActiveCallItem item)
{
CallItem = item;
}
}
}

View File

@@ -1,35 +0,0 @@
namespace PepperDash.Essentials.Core.Devices.Codec
{
public enum eCodecCallDirection
{
Unknown = 0, Incoming, Outgoing
}
public class CodecCallDirection
{
/// <summary>
/// Takes the Cisco call type and converts to the matching enum
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static eCodecCallDirection ConvertToDirectionEnum(string s)
{
switch (s.ToLower())
{
case "incoming":
{
return eCodecCallDirection.Incoming;
}
case "outgoing":
{
return eCodecCallDirection.Outgoing;
}
default:
return eCodecCallDirection.Unknown;
}
}
}
}

View File

@@ -1,83 +0,0 @@
namespace PepperDash.Essentials.Core.Devices.Codec
{
public enum eCodecCallStatus
{
Unknown = 0,
Connected,
Connecting,
Dialing,
Disconnected,
Disconnecting,
EarlyMedia,
Idle,
OnHold,
Ringing,
Preserved,
RemotePreserved,
}
public class CodecCallStatus
{
/// <summary>
/// Takes the Cisco call type and converts to the matching enum
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static eCodecCallStatus ConvertToStatusEnum(string s)
{
switch (s)
{
case "Connected":
{
return eCodecCallStatus.Connected;
}
case "Connecting":
{
return eCodecCallStatus.Connecting;
}
case "Dialling":
{
return eCodecCallStatus.Dialing;
}
case "Disconnected":
{
return eCodecCallStatus.Disconnected;
}
case "Disconnecting":
{
return eCodecCallStatus.Disconnecting;
}
case "EarlyMedia":
{
return eCodecCallStatus.EarlyMedia;
}
case "Idle":
{
return eCodecCallStatus.Idle;
}
case "OnHold":
{
return eCodecCallStatus.OnHold;
}
case "Ringing":
{
return eCodecCallStatus.Ringing;
}
case "Preserved":
{
return eCodecCallStatus.Preserved;
}
case "RemotePreserved":
{
return eCodecCallStatus.RemotePreserved;
}
default:
return eCodecCallStatus.Unknown;
}
}
}
}

View File

@@ -1,48 +0,0 @@
namespace PepperDash.Essentials.Core.Devices.Codec
{
public enum eCodecCallType
{
Unknown = 0,
Audio,
Video,
AudioCanEscalate,
ForwardAllCall
}
public class CodecCallType
{
/// <summary>
/// Takes the Cisco call type and converts to the matching enum
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static eCodecCallType ConvertToTypeEnum(string s)
{
switch (s)
{
case "Audio":
{
return eCodecCallType.Audio;
}
case "Video":
{
return eCodecCallType.Video;
}
case "AudioCanEscalate":
{
return eCodecCallType.AudioCanEscalate;
}
case "ForwardAllCall":
{
return eCodecCallType.ForwardAllCall;
}
default:
return eCodecCallType.Unknown;
}
}
}
}

View File

@@ -1,36 +0,0 @@
namespace PepperDash.Essentials.Core.Devices.Codec
{
public enum eMeetingPrivacy
{
Unknown = 0,
Public,
Private
}
public class CodecCallPrivacy
{
/// <summary>
/// Takes the Cisco privacy type and converts to the matching enum
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static eMeetingPrivacy ConvertToDirectionEnum(string s)
{
switch (s.ToLower())
{
case "public":
{
return eMeetingPrivacy.Public;
}
case "private":
{
return eMeetingPrivacy.Private;
}
default:
return eMeetingPrivacy.Unknown;
}
}
}
}

View File

@@ -1,10 +0,0 @@
namespace PepperDash.Essentials.Core.Devices.Codec
{
/// <summary>
/// Defines minimum volume controls for a codec device with dialing capabilities
/// </summary>
public interface ICodecAudio : IBasicVolumeWithFeedback, IPrivacy
{
}
}

View File

@@ -1,22 +0,0 @@
using System.Collections.Generic;
namespace PepperDash.Essentials.Core.Devices.Codec
{
public interface IHasCallFavorites
{
CodecCallFavorites CallFavorites { get; }
}
/// <summary>
/// Represents favorites entries for a codec device
/// </summary>
public class CodecCallFavorites
{
public List<CodecActiveCallItem> Favorites { get; set; }
public CodecCallFavorites()
{
Favorites = new List<CodecActiveCallItem>();
}
}
}

View File

@@ -1,88 +0,0 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace PepperDash.Essentials.Core.Devices.Codec
{
public interface IHasCallHistory
{
CodecCallHistory CallHistory { get; }
void RemoveCallHistoryEntry(CodecCallHistory.CallHistoryEntry entry);
}
public enum eCodecOccurrenceType
{
Unknown = 0,
Placed,
Received,
NoAnswer
}
/// <summary>
/// Represents the recent call history for a codec device
/// </summary>
public class CodecCallHistory
{
public event EventHandler<EventArgs> RecentCallsListHasChanged;
public List<CallHistoryEntry> RecentCalls { get; private set; }
/// <summary>
/// Item that gets added to the list when there are no recent calls in history
/// </summary>
readonly CallHistoryEntry _listEmptyEntry;
public CallHistoryEntry ListEmptyEntry
{
get { return _listEmptyEntry; }
}
public CodecCallHistory()
{
_listEmptyEntry = new CallHistoryEntry() { Name = "No Recent Calls" };
RecentCalls = new List<CallHistoryEntry> {_listEmptyEntry};
}
private void OnRecentCallsListChange()
{
var handler = RecentCallsListHasChanged;
if (handler != null)
{
handler(this, new EventArgs());
}
}
public void RemoveEntry(CallHistoryEntry entry)
{
RecentCalls.Remove(entry);
OnRecentCallsListChange();
}
public void UpdateCallHistory(List<CallHistoryEntry> newList)
{
RecentCalls = newList;
OnRecentCallsListChange();
}
/// <summary>
/// Generic call history entry, not device specific
/// </summary>
public class CallHistoryEntry : CodecActiveCallItem
{
[JsonConverter(typeof (IsoDateTimeConverter))]
[JsonProperty("startTime")]
public DateTime StartTime { get; set; }
[JsonConverter(typeof (StringEnumConverter))]
[JsonProperty("occurrenceType")]
public eCodecOccurrenceType OccurrenceType { get; set; }
[JsonProperty("occurrenceHistoryId")]
public string OccurrenceHistoryId { get; set; }
}
}
}

View File

@@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Core.Devices.Codec
{
public interface IHasContentSharing
{
BoolFeedback SharingContentIsOnFeedback { get; }
StringFeedback SharingSourceFeedback { get; }
bool AutoShareContentWhileInCall { get; }
void StartSharing();
void StopSharing();
}
}

View File

@@ -1,24 +0,0 @@
using System;
namespace PepperDash.Essentials.Core.Devices.Codec
{
/// <summary>
/// Requirements for a device that has dialing capabilities
/// </summary>
public interface IHasDialer
{
// Add requirements for Dialer functionality
event EventHandler<CodecCallStatusItemChangeEventArgs> CallStatusChange;
void Dial(string number);
void EndCall(CodecActiveCallItem activeCall);
void EndAllCalls();
void AcceptCall(CodecActiveCallItem item);
void RejectCall(CodecActiveCallItem item);
void SendDtmf(string digit);
bool IsInCall { get; }
}
}

View File

@@ -1,223 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using PepperDash.Essentials.Core.Devices.VideoCodec;
namespace PepperDash.Essentials.Core.Devices.Codec
{
/// <summary>
/// Defines the API for codecs with a directory
/// </summary>
public interface IHasDirectory
{
event EventHandler<DirectoryEventArgs> DirectoryResultReturned;
CodecDirectory DirectoryRoot { get; }
CodecDirectory CurrentDirectoryResult { get; }
CodecPhonebookSyncState PhonebookSyncState { get; }
void SearchDirectory(string searchString);
void GetDirectoryFolderContents(string folderId);
void SetCurrentDirectoryToRoot();
void GetDirectoryParentFolderContents();
BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; }
/// <summary>
/// Tracks the directory browse history when browsing beyond the root directory
/// </summary>
List<CodecDirectory> DirectoryBrowseHistory { get; }
}
/// <summary>
///
/// </summary>
public class DirectoryEventArgs : EventArgs
{
public CodecDirectory Directory { get; set; }
public bool DirectoryIsOnRoot { get; set; }
}
/// <summary>
/// Represents a codec directory
/// </summary>
public class CodecDirectory
{
/// <summary>
/// Represents the contents of the directory
/// </summary>
[JsonProperty("directoryResults")]
public List<DirectoryItem> CurrentDirectoryResults { get; private set; }
/// <summary>
/// Used to store the ID of the current folder for CurrentDirectoryResults
/// </summary>
[JsonProperty("resultsFolderId")]
public string ResultsFolderId { get; set; }
public CodecDirectory()
{
CurrentDirectoryResults = new List<DirectoryItem>();
}
/// <summary>
/// Adds folders to the directory
/// </summary>
/// <param name="folders"></param>
public void AddFoldersToDirectory(List<DirectoryItem> folders)
{
if(folders != null)
CurrentDirectoryResults.AddRange(folders);
SortDirectory();
}
/// <summary>
/// Adds contacts to the directory
/// </summary>
/// <param name="contacts"></param>
public void AddContactsToDirectory(List<DirectoryItem> contacts)
{
if(contacts != null)
CurrentDirectoryResults.AddRange(contacts);
SortDirectory();
}
/// <summary>
/// Sorts the DirectoryResults list to display all folders alphabetically, then all contacts alphabetically
/// </summary>
private void SortDirectory()
{
var sortedFolders = new List<DirectoryItem>();
sortedFolders.AddRange(CurrentDirectoryResults.Where(f => f is DirectoryFolder));
sortedFolders.OrderBy(f => f.Name);
var sortedContacts = new List<DirectoryItem>();
sortedContacts.AddRange(CurrentDirectoryResults.Where(c => c is DirectoryContact));
sortedFolders.OrderBy(c => c.Name);
CurrentDirectoryResults.Clear();
CurrentDirectoryResults.AddRange(sortedFolders);
CurrentDirectoryResults.AddRange(sortedContacts);
}
}
/// <summary>
/// Used to decorate a contact to indicate it can be invided to a meeting
/// </summary>
public interface IInvitableContact
{
}
/// <summary>
/// Represents an item in the directory
/// </summary>
public class DirectoryItem : ICloneable
{
public object Clone()
{
return this.MemberwiseClone();
}
[JsonProperty("folderId")]
public string FolderId { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
/// <summary>
/// Represents a folder type DirectoryItem
/// </summary>
public class DirectoryFolder : DirectoryItem
{
[JsonProperty("contacts")]
public List<DirectoryContact> Contacts { get; set; }
[JsonProperty("parentFolderId")]
public string ParentFolderId { get; set; }
public DirectoryFolder()
{
Contacts = new List<DirectoryContact>();
}
}
/// <summary>
/// Represents a contact type DirectoryItem
/// </summary>
public class DirectoryContact : DirectoryItem
{
[JsonProperty("contactId")]
public string ContactId { get; set; }
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("contactMethods")]
public List<ContactMethod> ContactMethods { get; set; }
public DirectoryContact()
{
ContactMethods = new List<ContactMethod>();
}
}
/// <summary>
/// Represents a method of contact for a contact
/// </summary>
public class ContactMethod
{
[JsonProperty("contactMethodId")]
public string ContactMethodId { get; set; }
[JsonProperty("number")]
public string Number { get; set; }
[JsonProperty("device")]
[JsonConverter(typeof(StringEnumConverter))]
public eContactMethodDevice Device { get; set; }
[JsonProperty("callType")]
[JsonConverter(typeof(StringEnumConverter))]
public eContactMethodCallType CallType { get; set; }
}
/// <summary>
///
/// </summary>
public enum eContactMethodDevice
{
Unknown = 0,
Mobile,
Other,
Telephone,
Video
}
/// <summary>
///
/// </summary>
public enum eContactMethodCallType
{
Unknown = 0,
Audio,
Video
}
}

View File

@@ -1,165 +0,0 @@
using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core.Devices.Codec
{
public enum eMeetingEventChangeType
{
Unkown = 0,
MeetingStartWarning,
MeetingStart,
MeetingEndWarning,
MeetingEnd
}
public interface IHasScheduleAwareness
{
CodecScheduleAwareness CodecSchedule { get; }
void GetSchedule();
}
public class CodecScheduleAwareness
{
List<Meeting> _Meetings;
public event EventHandler<MeetingEventArgs> MeetingEventChange;
public event EventHandler<EventArgs> MeetingsListHasChanged;
/// <summary>
/// Setter triggers MeetingsListHasChanged event
/// </summary>
public List<Meeting> Meetings
{
get
{
return _Meetings;
}
set
{
_Meetings = value;
var handler = MeetingsListHasChanged;
if (handler != null)
{
handler(this, new EventArgs());
}
}
}
private CTimer ScheduleChecker;
public CodecScheduleAwareness()
{
Meetings = new List<Meeting>();
ScheduleChecker = new CTimer(CheckSchedule, null, 1000, 1000);
}
private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting)
{
var handler = MeetingEventChange;
if (handler != null)
{
handler(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting });
}
}
private void CheckSchedule(object o)
{
// Iterate the meeting list and check if any meeting need to do anythingk
const double meetingTimeEpsilon = 0.0001;
foreach (Meeting m in Meetings)
{
eMeetingEventChangeType changeType = eMeetingEventChangeType.Unkown;
if (m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes) // Meeting is about to start
changeType = eMeetingEventChangeType.MeetingStartWarning;
else if (Math.Abs(m.TimeToMeetingStart.TotalMinutes) < meetingTimeEpsilon) // Meeting Start
changeType = eMeetingEventChangeType.MeetingStart;
else if (m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes) // Meeting is about to end
changeType = eMeetingEventChangeType.MeetingEndWarning;
else if (Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting has ended
changeType = eMeetingEventChangeType.MeetingEnd;
if (changeType != eMeetingEventChangeType.Unkown)
OnMeetingChange(changeType, m);
}
}
}
/// <summary>
/// Generic class to represent a meeting (Cisco or Polycom OBTP or Fusion)
/// </summary>
public class Meeting
{
public TimeSpan MeetingWarningMinutes = TimeSpan.FromMinutes(5);
public string Id { get; set; }
public string Organizer { get; set; }
public string Title { get; set; }
public string Agenda { get; set; }
public TimeSpan TimeToMeetingStart
{
get
{
return StartTime - DateTime.Now;
}
}
public TimeSpan TimeToMeetingEnd
{
get
{
return EndTime - DateTime.Now;
}
}
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public TimeSpan Duration
{
get
{
return EndTime - StartTime;
}
}
public eMeetingPrivacy Privacy { get; set; }
public bool Joinable
{
get
{
return StartTime.AddMinutes(-5) <= DateTime.Now
&& DateTime.Now <= EndTime; //.AddMinutes(-5);
}
}
//public string ConferenceNumberToDial { get; set; }
public string ConferencePassword { get; set; }
public bool IsOneButtonToPushMeeting { get; set; }
public List<Call> Calls { get; private set; }
public Meeting()
{
Calls = new List<Call>();
}
}
public class Call
{
public string Number { get; set; }
public string Protocol { get; set; }
public string CallRate { get; set; }
public string CallType { get; set; }
}
public class MeetingEventArgs : EventArgs
{
public eMeetingEventChangeType ChangeType { get; set; }
public Meeting Meeting { get; set; }
}
}

View File

@@ -1,18 +0,0 @@
namespace PepperDash.Essentials.Core.Devices.AudioCodec
{
/// <summary>
/// Implements a common set of data about a codec
/// </summary>
public interface IAudioCodecInfo
{
AudioCodecInfo CodecInfo { get; }
}
/// <summary>
/// Stores general information about a codec
/// </summary>
public abstract class AudioCodecInfo
{
public abstract string PhoneNumber { get; set; }
}
}

View File

@@ -1,16 +0,0 @@
namespace PepperDash.Essentials.Core.Devices.AudioCodec
{
/// <summary>
/// For rooms that have audio codec
/// </summary>
public interface IHasAudioCodec
{
AudioCodecBase AudioCodec { get; }
BoolFeedback InCallFeedback { get; }
///// <summary>
///// Make this more specific
///// </summary>
//List<PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem> ActiveCalls { get; }
}
}

View File

@@ -1,22 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Core.VideoCodec
{
/// <summary>
/// Defines the required elements for layout control
/// </summary>
public interface IHasCodecLayouts
{
StringFeedback LocalLayoutFeedback { get; }
void LocalLayoutToggle();
void LocalLayoutToggleSingleProminent();
void MinMaxLayoutToggle();
}
}

View File

@@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Core.VideoCodec
{
/// <summary>
/// Defines the requred elements for selfview control
/// </summary>
public interface IHasCodecSelfView
{
BoolFeedback SelfviewIsOnFeedback { get; }
bool ShowSelfViewByDefault { get; }
void SelfViewModeOn();
void SelfViewModeOff();
void SelfViewModeToggle();
}
}

View File

@@ -1,32 +0,0 @@
namespace PepperDash.Essentials.Core.Devices.VideoCodec
{
/// <summary>
/// For rooms that have video codec
/// </summary>
public interface IHasVideoCodec
{
VideoCodecBase VideoCodec { get; }
BoolFeedback InCallFeedback { get; }
///// <summary>
///// Make this more specific
///// </summary>
//List<PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem> ActiveCalls { get; }
/// <summary>
/// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis
/// </summary>
IntFeedback CallTypeFeedback { get; }
/// <summary>
///
/// </summary>
BoolFeedback PrivacyModeIsOnFeedback { get; }
/// <summary>
/// When something in the room is sharing with the far end or through other means
/// </summary>
BoolFeedback IsSharingFeedback { get; }
}
}

View File

@@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core.Devices.Codec
{
/// <summary>
/// Implements a common set of data about a codec
/// </summary>
public interface iVideoCodecInfo
{
VideoCodecInfo CodecInfo { get; }
}
/// <summary>
/// Stores general information about a codec
/// </summary>
public abstract class VideoCodecInfo
{
public abstract bool MultiSiteOptionIsEnabled { get; }
public abstract string IpAddress { get; }
public abstract string SipPhoneNumber { get; }
public abstract string E164Alias { get; }
public abstract string H323Id { get; }
public abstract string SipUri { get; }
public abstract bool AutoAnswerEnabled { get; }
}
}

View File

@@ -1,99 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using PepperDash.Essentials.Core.Devices.Codec;
namespace PepperDash.Essentials.Core.Devices.AudioCodec
{
public abstract class AudioCodecBase : EssentialsDevice, IHasDialer, IUsageTracking, IAudioCodecInfo
{
public event EventHandler<CodecCallStatusItemChangeEventArgs> CallStatusChange;
public AudioCodecInfo CodecInfo { get; protected set; }
#region IUsageTracking Members
/// <summary>
/// This object can be added by outside users of this class to provide usage tracking
/// for various services
/// </summary>
public UsageTracking UsageTracker { get; set; }
#endregion
/// <summary>
/// Returns true when any call is not in state Unknown, Disconnecting, Disconnected
/// </summary>
public bool IsInCall
{
get
{
bool value;
if (ActiveCalls != null)
value = ActiveCalls.Any(c => c.IsActiveCall);
else
value = false;
return value;
}
}
// In most cases only a single call can be active
public List<CodecActiveCallItem> ActiveCalls { get; set; }
public AudioCodecBase(string key, string name)
: base(key, name)
{
ActiveCalls = new List<CodecActiveCallItem>();
}
/// <summary>
/// Helper method to fire CallStatusChange event with old and new status
/// </summary>
protected void SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus newStatus, CodecActiveCallItem call)
{
call.Status = newStatus;
OnCallStatusChange(call);
}
/// <summary>
///
/// </summary>
/// <param name="previousStatus"></param>
/// <param name="newStatus"></param>
/// <param name="item"></param>
protected void OnCallStatusChange(CodecActiveCallItem item)
{
var handler = CallStatusChange;
if (handler != null)
handler(this, new CodecCallStatusItemChangeEventArgs(item));
if (UsageTracker != null)
{
if (IsInCall && !UsageTracker.UsageTrackingStarted)
UsageTracker.StartDeviceUsage();
else if (UsageTracker.UsageTrackingStarted && !IsInCall)
UsageTracker.EndDeviceUsage();
}
}
#region IHasDialer Members
public abstract void Dial(string number);
public abstract void EndCall(CodecActiveCallItem activeCall);
public abstract void EndAllCalls();
public abstract void AcceptCall(CodecActiveCallItem item);
public abstract void RejectCall(CodecActiveCallItem item);
public abstract void SendDtmf(string digit);
#endregion
}
}

View File

@@ -1,323 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Routing;
using PepperDash.Essentials.Core.Devices.Codec;
namespace PepperDash.Essentials.Core.Devices.VideoCodec
{
public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingInputsOutputs,
IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo
{
/// <summary>
/// Fires when the status of any active, dialing, or incoming call changes or is new
/// </summary>
public event EventHandler<CodecCallStatusItemChangeEventArgs> CallStatusChange;
public event EventHandler<EventArgs> IsReadyChange;
public IBasicCommunication Communication { get; protected set; }
#region IUsageTracking Members
/// <summary>
/// This object can be added by outside users of this class to provide usage tracking
/// for various services
/// </summary>
public UsageTracking UsageTracker { get; set; }
#endregion
/// <summary>
/// An internal pseudo-source that is routable and connected to the osd input
/// </summary>
public DummyRoutingInputsDevice OsdSource { get; protected set; }
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
/// <summary>
/// Returns true when any call is not in state Unknown, Disconnecting, Disconnected
/// </summary>
public bool IsInCall
{
get
{
bool value;
if (ActiveCalls != null)
value = ActiveCalls.Any(c => c.IsActiveCall);
else
value = false;
return value;
}
}
public BoolFeedback StandbyIsOnFeedback { get; private set; }
abstract protected Func<bool> PrivacyModeIsOnFeedbackFunc { get; }
abstract protected Func<int> VolumeLevelFeedbackFunc { get; }
abstract protected Func<bool> MuteFeedbackFunc { get; }
abstract protected Func<bool> StandbyIsOnFeedbackFunc { get; }
public List<CodecActiveCallItem> ActiveCalls { get; set; }
public VideoCodecInfo CodecInfo { get; protected set; }
public bool ShowSelfViewByDefault { get; protected set; }
public bool IsReady { get; protected set; }
public VideoCodecBase(DeviceConfig config)
: base(config)
{
StandbyIsOnFeedback = new BoolFeedback(StandbyIsOnFeedbackFunc);
PrivacyModeIsOnFeedback = new BoolFeedback(PrivacyModeIsOnFeedbackFunc);
VolumeLevelFeedback = new IntFeedback(VolumeLevelFeedbackFunc);
MuteFeedback = new BoolFeedback(MuteFeedbackFunc);
SharingSourceFeedback = new StringFeedback(SharingSourceFeedbackFunc);
SharingContentIsOnFeedback = new BoolFeedback(SharingContentIsOnFeedbackFunc);
InputPorts = new RoutingPortCollection<RoutingInputPort>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
ActiveCalls = new List<CodecActiveCallItem>();
}
#region IHasDialer Members
public abstract void Dial(string number);
public abstract void Dial(Meeting meeting);
public virtual void Dial(IInvitableContact contact)
{
}
public abstract void EndCall(CodecActiveCallItem call);
public abstract void EndAllCalls();
public abstract void AcceptCall(CodecActiveCallItem call);
public abstract void RejectCall(CodecActiveCallItem call);
public abstract void SendDtmf(string s);
#endregion
public virtual List<Feedback> Feedbacks
{
get
{
return new List<Feedback>
{
PrivacyModeIsOnFeedback,
SharingSourceFeedback
};
}
}
public abstract void ExecuteSwitch(object selector);
/// <summary>
/// Helper method to fire CallStatusChange event with old and new status
/// </summary>
protected void SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus newStatus, CodecActiveCallItem call)
{
call.Status = newStatus;
OnCallStatusChange(call);
}
/// <summary>
///
/// </summary>
/// <param name="previousStatus"></param>
/// <param name="newStatus"></param>
/// <param name="item"></param>
protected void OnCallStatusChange(CodecActiveCallItem item)
{
var handler = CallStatusChange;
if (handler != null)
handler(this, new CodecCallStatusItemChangeEventArgs(item));
if (AutoShareContentWhileInCall)
StartSharing();
if (UsageTracker != null)
{
if (IsInCall && !UsageTracker.UsageTrackingStarted)
UsageTracker.StartDeviceUsage();
else if (UsageTracker.UsageTrackingStarted && !IsInCall)
UsageTracker.EndDeviceUsage();
}
}
/// <summary>
/// Sets IsReady property and fires the event. Used for dependent classes to sync up their data.
/// </summary>
protected void SetIsReady()
{
IsReady = true;
var h = IsReadyChange;
if(h != null)
h(this, new EventArgs());
}
#region ICodecAudio Members
public abstract void PrivacyModeOn();
public abstract void PrivacyModeOff();
public abstract void PrivacyModeToggle();
public BoolFeedback PrivacyModeIsOnFeedback { get; private set; }
public BoolFeedback MuteFeedback { get; private set; }
public abstract void MuteOff();
public abstract void MuteOn();
public abstract void SetVolume(ushort level);
public IntFeedback VolumeLevelFeedback { get; private set; }
public abstract void MuteToggle();
public abstract void VolumeDown(bool pressRelease);
public abstract void VolumeUp(bool pressRelease);
#endregion
#region IHasSharing Members
public abstract void StartSharing();
public abstract void StopSharing();
public bool AutoShareContentWhileInCall { get; protected set; }
public StringFeedback SharingSourceFeedback { get; private set; }
public BoolFeedback SharingContentIsOnFeedback { get; private set; }
abstract protected Func<string> SharingSourceFeedbackFunc { get; }
abstract protected Func<bool> SharingContentIsOnFeedbackFunc { get; }
#endregion
// **** DEBUGGING THINGS ****
/// <summary>
///
/// </summary>
public virtual void ListCalls()
{
var sb = new StringBuilder();
foreach (var c in ActiveCalls)
sb.AppendFormat("{0} {1} -- {2} {3}\n", c.Id, c.Number, c.Name, c.Status);
Debug.Console(1, this, "\n{0}\n", sb.ToString());
}
public abstract void StandbyActivate();
public abstract void StandbyDeactivate();
}
/// <summary>
/// Used to track the status of syncronizing the phonebook values when connecting to a codec or refreshing the phonebook info
/// </summary>
public class CodecPhonebookSyncState : IKeyed
{
bool _InitialSyncComplete;
public event EventHandler<EventArgs> InitialSyncCompleted;
public string Key { get; private set; }
public bool InitialSyncComplete
{
get { return _InitialSyncComplete; }
private set
{
if (value == true)
{
var handler = InitialSyncCompleted;
if (handler != null)
handler(this, new EventArgs());
}
_InitialSyncComplete = value;
}
}
public bool InitialPhonebookFoldersWasReceived { get; private set; }
public bool NumberOfContactsWasReceived { get; private set; }
public bool PhonebookRootEntriesWasRecieved { get; private set; }
public bool PhonebookHasFolders { get; private set; }
public int NumberOfContacts { get; private set; }
public CodecPhonebookSyncState(string key)
{
Key = key;
CodecDisconnected();
}
public void InitialPhonebookFoldersReceived()
{
InitialPhonebookFoldersWasReceived = true;
CheckSyncStatus();
}
public void PhonebookRootEntriesReceived()
{
PhonebookRootEntriesWasRecieved = true;
CheckSyncStatus();
}
public void SetPhonebookHasFolders(bool value)
{
PhonebookHasFolders = value;
Debug.Console(1, this, "Phonebook has folders: {0}", PhonebookHasFolders);
}
public void SetNumberOfContacts(int contacts)
{
NumberOfContacts = contacts;
NumberOfContactsWasReceived = true;
Debug.Console(1, this, "Phonebook contains {0} contacts.", NumberOfContacts);
CheckSyncStatus();
}
public void CodecDisconnected()
{
InitialPhonebookFoldersWasReceived = false;
PhonebookHasFolders = false;
NumberOfContacts = 0;
NumberOfContactsWasReceived = false;
}
void CheckSyncStatus()
{
if (InitialPhonebookFoldersWasReceived && NumberOfContactsWasReceived && PhonebookRootEntriesWasRecieved)
{
InitialSyncComplete = true;
Debug.Console(1, this, "Initial Phonebook Sync Complete!");
}
else
InitialSyncComplete = false;
}
}
}

View File

@@ -1,50 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Essentials.Core;
namespace PepperDash_Essentials_Core.Devices
{
public class DestinationListItem
{
[JsonProperty("sinkKey")]
public string SinkKey { get; set; }
private EssentialsDevice _sinkDevice;
[JsonIgnore]
public EssentialsDevice SinkDevice
{
get { return _sinkDevice ?? (_sinkDevice = DeviceManager.GetDeviceForKey(SinkKey) as EssentialsDevice); }
}
public string PreferredName
{
get
{
if (!string.IsNullOrEmpty(Name))
{
return Name;
}
return SinkDevice == null ? "---" : SinkDevice.Name;
}
}
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("includeInDestinationList")]
public bool IncludeInDestinationList { get; set; }
[JsonProperty("order")]
public int Order { get; set; }
[JsonProperty("surfaceLocation")]
public int SurfaceLocation { get; set; }
[JsonProperty("verticalLocation")]
public int VerticalLocation { get; set; }
[JsonProperty("horizontalLocation")]
public int HorizontalLocation { get; set; }
}
}

View File

@@ -238,6 +238,42 @@ namespace PepperDash.Essentials.Core
}
}
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

View File

@@ -84,7 +84,7 @@ namespace PepperDash.Essentials.Core
{
Debug.Console(2, "Getting Description Attribute from class: '{0}'", typeof(T).FullName);
var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[];
string description = descriptionAttribute[0].Description;
string description = descriptionAttribute[0].Description;
var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[];
DeviceFactory.AddFactoryForType(typeName.ToLower(), description, typeof(T), BuildDevice);
}

View File

@@ -2,21 +2,21 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core
{
public interface IBasicVideoMute
{
void VideoMuteToggle();
}
public interface IBasicVideoMuteWithFeedback : IBasicVideoMute
{
BoolFeedback VideoMuteIsOn { get; }
void VideoMuteOn();
void VideoMuteOff();
}
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core
{
public interface IBasicVideoMute
{
void VideoMuteToggle();
}
public interface IBasicVideoMuteWithFeedback : IBasicVideoMute
{
BoolFeedback VideoMuteIsOn { get; }
void VideoMuteOn();
void VideoMuteOff();
}
}

View File

@@ -1,6 +1,13 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
@@ -24,11 +31,16 @@ namespace PepperDash.Essentials.Core
/// Returns the source Device for this, if it exists in DeviceManager
/// </summary>
[JsonIgnore]
public EssentialsDevice SourceDevice
public Device SourceDevice
{
get { return _sourceDevice ?? (_sourceDevice = DeviceManager.GetDeviceForKey(SourceKey) as EssentialsDevice); }
get
{
if (_SourceDevice == null)
_SourceDevice = DeviceManager.GetDeviceForKey(SourceKey) as Device;
return _SourceDevice;
}
}
private EssentialsDevice _sourceDevice;
Device _SourceDevice;
/// <summary>
/// Gets either the source's Name or this AlternateName property, if
@@ -39,12 +51,13 @@ namespace PepperDash.Essentials.Core
{
get
{
if (!string.IsNullOrEmpty(Name))
{
return Name;
}
return SourceDevice == null ? "---" : SourceDevice.Name;
if (string.IsNullOrEmpty(Name))
{
if (SourceDevice == null)
return "---";
return SourceDevice.Name;
}
return Name;
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash_Essentials_Core
{
public class IsReadyEventArgs : EventArgs
{
public bool IsReady { get; set; }
public IsReadyEventArgs(bool data)
{
IsReady = data;
}
}
public interface IHasReady
{
event EventHandler<IsReadyEventArgs> IsReadyEvent;
bool IsReady { get; }
}
}

View File

@@ -17,10 +17,10 @@ using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Rooms;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.Fusion
{
public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupancyStatusProvider

View File

@@ -10,7 +10,6 @@ using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Core.Rooms;
namespace PepperDash.Essentials.Core.Fusion
{

View File

@@ -6,134 +6,192 @@ using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.Gateways;
using Newtonsoft.Json;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash_Essentials_Core;
namespace PepperDash.Essentials.Core
namespace PepperDash.Essentials.Core
{
[Description("Wrapper class for Crestron Infinet-EX Gateways")]
public class CenRfgwController : CrestronGenericBaseDevice
{
private GatewayBase _Gateway;
public GatewayBase GateWay { get { return _Gateway; } }
/// <summary>
/// Constructor for the on-board gateway
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
public CenRfgwController(string key, string name, GatewayBase gateway) :
base(key, name, gateway)
{
_Gateway = gateway;
}
public static CenRfgwController GetNewExGatewayController(string key, string name, ushort ipId, ushort cresnetId, string gatewayType)
{
eExGatewayType type = (eExGatewayType)Enum.Parse(typeof(eExGatewayType), gatewayType, true);
try
{
var cs = Global.ControlSystem;
GatewayBase gw = null;
switch (type)
{
case eExGatewayType.Ethernet:
gw = new CenRfgwEx(ipId, cs);
break;
case eExGatewayType.EthernetShared:
gw = new CenRfgwExEthernetSharable(ipId, cs);
break;
case eExGatewayType.Cresnet:
gw = new CenRfgwExCresnet(cresnetId, cs);
break;
}
return new CenRfgwController(key, name, gw);
}
catch (Exception)
{
Debug.Console(0, "ERROR: Cannot create EX Gateway, id {0}, type {1}", type == eExGatewayType.Cresnet ? cresnetId : ipId, gatewayType);
return null;
}
}
public static CenRfgwController GetNewErGatewayController(string key, string name, ushort ipId, ushort cresnetId, string gatewayType)
{
eExGatewayType type = (eExGatewayType)Enum.Parse(typeof(eExGatewayType), gatewayType, true);
try
{
var cs = Global.ControlSystem;
GatewayBase gw = null;
switch (type)
{
case eExGatewayType.Ethernet:
gw = new CenErfgwPoe(ipId, cs);
break;
case eExGatewayType.EthernetShared:
gw = new CenErfgwPoeEthernetSharable(ipId, cs);
break;
case eExGatewayType.Cresnet:
gw = new CenErfgwPoeCresnet(cresnetId, cs);
break;
}
return new CenRfgwController(key, name, gw);
}
catch (Exception)
{
Debug.Console(0, "ERROR: Cannot create ER Gateway, id {0}, type {1}", type== eExGatewayType.Cresnet ? cresnetId : ipId, gatewayType);
return null;
}
}
}
public enum eExGatewayType
{
Ethernet, EthernetShared, Cresnet
}
[Description("Wrapper class for Crestron Infinet-EX Gateways")]
public class CenRfgwController : CrestronGenericBaseDevice, IHasReady
{
public event EventHandler<IsReadyEventArgs> IsReadyEvent;
public bool IsReady { get; private set; }
#region Factory
public class CenRfgwControllerFactory : EssentialsDeviceFactory<CenRfgwController>
{
public CenRfgwControllerFactory()
{
TypeNames = new List<string>() { "cenrfgwex", "cenerfgwpoe" };
}
private GatewayBase _gateway;
public override EssentialsDevice BuildDevice(DeviceConfig dc)
public GatewayBase GateWay
{
Debug.Console(1, "Factory Attempting to create new CEN-GWEXER Device");
var props = JsonConvert.DeserializeObject<EssentialsRfGatewayConfig>(dc.Properties.ToString());
var type = dc.Type.ToLower();
var control = props.Control;
var ipid = control.IpIdInt;
var cresnetId = control.CresnetIdInt;
var gatewayType = props.GatewayType;
switch (type)
{
case ("cenrfgwex"):
return CenRfgwController.GetNewExGatewayController(dc.Key, dc.Name,
(ushort)ipid, (ushort)cresnetId, gatewayType);
case ("cenerfgwpoe"):
return CenRfgwController.GetNewErGatewayController(dc.Key, dc.Name,
(ushort)ipid, (ushort)cresnetId, gatewayType);
default:
return null;
}
get { return _gateway; }
}
/// <summary>
/// Constructor for the on-board gateway
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
/// <param name="gateway"></param>
public CenRfgwController(string key, string name, GatewayBase gateway) :
base(key, name, gateway)
{
_gateway = gateway;
IsReady = true;
FireIsReadyEvent(IsReady);
}
public CenRfgwController(string key, Func<DeviceConfig, GatewayBase> preActivationFunc, DeviceConfig config) :
base(key, config.Name)
{
IsReady = false;
FireIsReadyEvent(IsReady);
AddPreActivationAction(() =>
{
_gateway = preActivationFunc(config);
IsReady = true;
RegisterCrestronGenericBase(_gateway);
FireIsReadyEvent(IsReady);
});
}
public static GatewayBase GetNewIpRfGateway(DeviceConfig dc)
{
var control = CommFactory.GetControlPropertiesConfig(dc);
var type = dc.Type;
var ipId = control.IpIdInt;
if (type.Equals("cenrfgwex", StringComparison.InvariantCultureIgnoreCase))
{
return new CenRfgwEx(ipId, Global.ControlSystem);
}
if (type.Equals("cenerfgwpoe", StringComparison.InvariantCultureIgnoreCase))
{
return new CenErfgwPoe(ipId, Global.ControlSystem);
}
return null;
}
private void FireIsReadyEvent(bool data)
{
var handler = IsReadyEvent;
if (handler == null) return;
handler(this, new IsReadyEventArgs(data));
}
public static GatewayBase GetNewSharedIpRfGateway(DeviceConfig dc)
{
var control = CommFactory.GetControlPropertiesConfig(dc);
var ipId = control.IpIdInt;
if (dc.Type.Equals("cenrfgwex", StringComparison.InvariantCultureIgnoreCase))
{
return new CenRfgwExEthernetSharable(ipId, Global.ControlSystem);
}
if (dc.Type.Equals("cenerfgwpoe", StringComparison.InvariantCultureIgnoreCase))
{
return new CenErfgwPoeEthernetSharable(ipId, Global.ControlSystem);
}
return null;
}
public static GatewayBase GetCenRfgwCresnetController(DeviceConfig dc)
{
var control = CommFactory.GetControlPropertiesConfig(dc);
var type = dc.Type;
var cresnetId = control.CresnetIdInt;
var branchId = control.ControlPortNumber;
var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey;
if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase))
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new CenRfgw", parentKey);
if (type.Equals("cenerfgwpoe", StringComparison.InvariantCultureIgnoreCase))
{
return new CenErfgwPoeCresnet(cresnetId, Global.ControlSystem);
}
if (type.Equals("cenrfgwex", StringComparison.InvariantCultureIgnoreCase))
{
return new CenRfgwExCresnet(cresnetId, Global.ControlSystem);
}
}
var cresnetBridge = DeviceManager.GetDeviceForKey(parentKey) as ICresnetBridge;
if (cresnetBridge != null)
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new CenRfgw", parentKey);
if (type.Equals("cenerfgwpoe", StringComparison.InvariantCultureIgnoreCase))
{
return new CenErfgwPoeCresnet(cresnetId, cresnetBridge.Branches[branchId]);
}
if (type.Equals("cenrfgwex", StringComparison.InvariantCultureIgnoreCase))
{
return new CenRfgwExCresnet(cresnetId, cresnetBridge.Branches[branchId]);
}
}
Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey);
return null;
}
public enum EExGatewayType
{
Ethernet,
EthernetShared,
Cresnet
}
#region Factory
public class CenRfgwControllerFactory : EssentialsDeviceFactory<CenRfgwController>
{
public CenRfgwControllerFactory()
{
TypeNames = new List<string> {"cenrfgwex", "cenerfgwpoe"};
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new CEN-GWEXER Device");
var props = JsonConvert.DeserializeObject<EssentialsRfGatewayConfig>(dc.Properties.ToString());
EExGatewayType gatewayType =
(EExGatewayType) Enum.Parse(typeof (EExGatewayType), props.GatewayType, true);
switch (gatewayType)
{
case (EExGatewayType.Ethernet):
return new CenRfgwController(dc.Key, dc.Name, GetNewIpRfGateway(dc));
case (EExGatewayType.EthernetShared):
return new CenRfgwController(dc.Key, dc.Name, GetNewSharedIpRfGateway(dc));
case (EExGatewayType.Cresnet):
return new CenRfgwController(dc.Key, GetCenRfgwCresnetController, dc);
}
return null;
}
}
#endregion
}
#endregion
}
}

View File

@@ -1,488 +1,488 @@
using System;
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using Crestron.SimplSharp.Reflection;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core
{
public static class JoinMapHelper
{
/// <summary>
/// Attempts to get the serialized join map from config
/// </summary>
/// <param name="joinMapKey"></param>
/// <returns></returns>
public static string GetSerializedJoinMapForDevice(string joinMapKey)
{
if (string.IsNullOrEmpty(joinMapKey))
return null;
var joinMap = ConfigReader.ConfigObject.JoinMaps[joinMapKey];
return joinMap;
}
/// <summary>
/// Attempts to get the serialized join map from config
/// </summary>
/// <param name="joinMapKey"></param>
/// <returns></returns>
public static string GetJoinMapForDevice(string joinMapKey)
{
return GetSerializedJoinMapForDevice(joinMapKey);
}
/// <summary>
/// Attempts to find a custom join map by key and returns it deserialized if found
/// </summary>
/// <param name="joinMapKey"></param>
/// <returns></returns>
public static Dictionary<string, JoinData> TryGetJoinMapAdvancedForDevice(string joinMapKey)
{
if (string.IsNullOrEmpty(joinMapKey))
return null;
var joinMapSerialzed = ConfigReader.ConfigObject.JoinMaps[joinMapKey];
if (joinMapSerialzed == null) return null;
var joinMapData = JsonConvert.DeserializeObject<Dictionary<string, JoinData>>(joinMapSerialzed);
return joinMapData;
}
}
/// <summary>
/// Base class for join maps
/// </summary>
[Obsolete("This is being deprecated in favor of JoinMapBaseAdvanced")]
public abstract class JoinMapBase
{
/// <summary>
/// Modifies all the join numbers by adding the offset. This should never be called twice
/// </summary>
/// <param name="joinStart"></param>
public abstract void OffsetJoinNumbers(uint joinStart);
/// <summary>
/// The collection of joins and associated metadata
/// </summary>
public Dictionary<string, JoinMetadata> Joins = new Dictionary<string, JoinMetadata>();
/// <summary>
/// Prints the join information to console
/// </summary>
public void PrintJoinMapInfo()
{
Debug.Console(0, "{0}:\n", GetType().Name);
// Get the joins of each type and print them
Debug.Console(0, "Digitals:");
var digitals = Joins.Where(j => (j.Value.JoinType & eJoinType.Digital) == eJoinType.Digital).ToDictionary(j => j.Key, j => j.Value);
Debug.Console(2, "Found {0} Digital Joins", digitals.Count);
PrintJoinList(GetSortedJoins(digitals));
Debug.Console(0, "Analogs:");
var analogs = Joins.Where(j => (j.Value.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value);
Debug.Console(2, "Found {0} Analog Joins", analogs.Count);
PrintJoinList(GetSortedJoins(analogs));
Debug.Console(0, "Serials:");
var serials = Joins.Where(j => (j.Value.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value);
Debug.Console(2, "Found {0} Serial Joins", serials.Count);
PrintJoinList(GetSortedJoins(serials));
}
/// <summary>
/// Returns a sorted list by JoinNumber
/// </summary>
/// <param name="joins"></param>
/// <returns></returns>
List<KeyValuePair<string, JoinMetadata>> GetSortedJoins(Dictionary<string, JoinMetadata> joins)
{
var sortedJoins = joins.ToList();
sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber));
return sortedJoins;
}
void PrintJoinList(List<KeyValuePair<string, JoinMetadata>> joins)
{
foreach (var join in joins)
{
Debug.Console(0,
@"Join Number: {0} | Label: '{1}' | JoinSpan: '{2}' | Type: '{3}' | Capabilities: '{4}'",
join.Value.JoinNumber,
join.Value.Label,
join.Value.JoinSpan,
join.Value.JoinType.ToString(),
join.Value.JoinCapabilities.ToString());
}
}
/// <summary>
/// Returns the join number for the join with the specified key
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public uint GetJoinForKey(string key)
{
return Joins.ContainsKey(key) ? Joins[key].JoinNumber : 0;
}
/// <summary>
/// Returns the join span for the join with the specified key
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public uint GetJoinSpanForKey(string key)
{
return Joins.ContainsKey(key) ? Joins[key].JoinSpan : 0;
}
}
/// <summary>
/// Base class for join maps
/// </summary>
public abstract class JoinMapBaseAdvanced
{
protected uint JoinOffset;
/// <summary>
/// The collection of joins and associated metadata
/// </summary>
public Dictionary<string, JoinDataComplete> Joins { get; private set; }
protected JoinMapBaseAdvanced(uint joinStart)
{
Joins = new Dictionary<string, JoinDataComplete>();
JoinOffset = joinStart - 1;
}
protected JoinMapBaseAdvanced(uint joinStart, Type type):this(joinStart)
{
AddJoins(type);
}
protected void AddJoins(Type type)
{
// Add all the JoinDataComplete properties to the Joins Dictionary and pass in the offset
//Joins = this.GetType()
// .GetCType()
// .GetFields(BindingFlags.Public | BindingFlags.Instance)
// .Where(field => field.IsDefined(typeof(JoinNameAttribute), true))
// .Select(field => (JoinDataComplete)field.GetValue(this))
// .ToDictionary(join => join.GetNameAttribute(), join =>
// {
// join.SetJoinOffset(_joinOffset);
// return join;
// });
//type = this.GetType(); <- this wasn't working because 'this' was always the base class, never the derived class
var fields =
type.GetCType()
.GetFields(BindingFlags.Public | BindingFlags.Instance)
.Where(f => f.IsDefined(typeof (JoinNameAttribute), true));
foreach (var field in fields)
{
var childClass = Convert.ChangeType(this, type, null);
var value = field.GetValue(childClass) as JoinDataComplete; //this here is JoinMapBaseAdvanced, not the child class. JoinMapBaseAdvanced has no fields.
if (value == null)
{
Debug.Console(0, "Unable to caset base class to {0}", type.Name);
continue;
}
value.SetJoinOffset(JoinOffset);
var joinName = value.GetNameAttribute(field);
if (String.IsNullOrEmpty(joinName)) continue;
Joins.Add(joinName, value);
}
PrintJoinMapInfo();
}
/// <summary>
/// Prints the join information to console
/// </summary>
public void PrintJoinMapInfo()
{
Debug.Console(0, "{0}:\n", GetType().Name);
// Get the joins of each type and print them
Debug.Console(0, "Digitals:");
var digitals = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Digital) == eJoinType.Digital).ToDictionary(j => j.Key, j => j.Value);
Debug.Console(2, "Found {0} Digital Joins", digitals.Count);
PrintJoinList(GetSortedJoins(digitals));
Debug.Console(0, "Analogs:");
var analogs = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value);
Debug.Console(2, "Found {0} Analog Joins", analogs.Count);
PrintJoinList(GetSortedJoins(analogs));
Debug.Console(0, "Serials:");
var serials = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value);
Debug.Console(2, "Found {0} Serial Joins", serials.Count);
PrintJoinList(GetSortedJoins(serials));
}
/// <summary>
/// Returns a sorted list by JoinNumber
/// </summary>
/// <param name="joins"></param>
/// <returns></returns>
List<KeyValuePair<string, JoinDataComplete>> GetSortedJoins(Dictionary<string, JoinDataComplete> joins)
{
var sortedJoins = joins.ToList();
sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber));
return sortedJoins;
}
void PrintJoinList(List<KeyValuePair<string, JoinDataComplete>> joins)
{
foreach (var join in joins)
{
Debug.Console(0,
@"Join Number: {0} | JoinSpan: '{1}' | Label: '{2}' | Type: '{3}' | Capabilities: '{4}'",
join.Value.JoinNumber,
join.Value.JoinSpan,
join.Value.Metadata.Label,
join.Value.Metadata.JoinType.ToString(),
join.Value.Metadata.JoinCapabilities.ToString());
}
}
/// <summary>
/// Attempts to find the matching key for the custom join and if found overwrites the default JoinData with the custom
/// </summary>
/// <param name="joinData"></param>
public void SetCustomJoinData(Dictionary<string, JoinData> joinData)
{
foreach (var customJoinData in joinData)
{
var join = Joins[customJoinData.Key];
if (join != null)
{
join.SetCustomJoinData(customJoinData.Value);
}
else
{
Debug.Console(2, "No mathcing key found in join map for: '{0}'", customJoinData.Key);
}
}
PrintJoinMapInfo();
}
///// <summary>
///// Returns the join number for the join with the specified key
///// </summary>
///// <param name="key"></param>
///// <returns></returns>
//public uint GetJoinForKey(string key)
//{
// return Joins.ContainsKey(key) ? Joins[key].JoinNumber : 0;
//}
///// <summary>
///// Returns the join span for the join with the specified key
///// </summary>
///// <param name="key"></param>
///// <returns></returns>
//public uint GetJoinSpanForKey(string key)
//{
// return Joins.ContainsKey(key) ? Joins[key].JoinSpan : 0;
//}
}
/// <summary>
/// Read = Provides feedback to SIMPL
/// Write = Responds to sig values from SIMPL
/// </summary>
[Flags]
public enum eJoinCapabilities
{
None = 0,
ToSIMPL = 1,
FromSIMPL = 2,
ToFromSIMPL = ToSIMPL | FromSIMPL
}
[Flags]
public enum eJoinType
{
None = 0,
Digital = 1,
Analog = 2,
Serial = 4,
DigitalAnalog = Digital | Analog,
DigitalSerial = Digital | Serial,
AnalogSerial = Analog | Serial,
DigitalAnalogSerial = Digital | Analog | Serial
}
/// <summary>
/// Metadata describing the join
/// </summary>
public class JoinMetadata
using Crestron.SimplSharp.Reflection;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core
{
public static class JoinMapHelper
{
private string _description;
/// <summary>
/// Join number (based on join offset value)
/// </summary>
[JsonProperty("joinNumber")]
[Obsolete]
public uint JoinNumber { get; set; }
/// <summary>
/// Join range span. If join indicates the start of a range of joins, this indicated the maximum number of joins in the range
/// </summary>
[Obsolete]
[JsonProperty("joinSpan")]
public uint JoinSpan { get; set; }
/// <summary>
/// A label for the join to better describe its usage
/// </summary>
[Obsolete("Use Description instead")]
[JsonProperty("label")]
public string Label { get { return _description; } set { _description = value; } }
/// <summary>
/// A description for the join to better describe its usage
/// </summary>
[JsonProperty("description")]
public string Description { get { return _description; } set { _description = value; } }
/// <summary>
/// Signal type(s)
/// </summary>
[JsonProperty("joinType")]
public eJoinType JoinType { get; set; }
/// <summary>
/// Indicates whether the join is read and/or write
/// </summary>
[JsonProperty("joinCapabilities")]
public eJoinCapabilities JoinCapabilities { get; set; }
/// <summary>
/// Indicates a set of valid values (particularly if this translates to an enum
/// </summary>
[JsonProperty("validValues")]
public string[] ValidValues { get; set; }
}
/// <summary>
/// Data describing the join. Can be
/// </summary>
public class JoinData
{
/// <summary>
/// Join number (based on join offset value)
/// </summary>
[JsonProperty("joinNumber")]
public uint JoinNumber { get; set; }
/// <summary>
/// Join range span. If join indicates the start of a range of joins, this indicated the maximum number of joins in the range
/// </summary>
[JsonProperty("joinSpan")]
public uint JoinSpan { get; set; }
}
/// <summary>
/// A class to aggregate the JoinData and JoinMetadata for a join
/// </summary>
public class JoinDataComplete
{
private uint _joinOffset;
private JoinData _data;
public JoinMetadata Metadata { get; set; }
public JoinDataComplete(JoinData data, JoinMetadata metadata)
{
_data = data;
Metadata = metadata;
}
/// <summary>
/// Sets the join offset value
/// </summary>
/// <param name="joinOffset"></param>
public void SetJoinOffset(uint joinOffset)
{
_joinOffset = joinOffset;
}
/// <summary>
/// The join number (including the offset)
/// </summary>
public uint JoinNumber
{
get { return _data.JoinNumber+ _joinOffset; }
set { _data.JoinNumber = value; }
}
public uint JoinSpan
{
get { return _data.JoinSpan; }
}
public void SetCustomJoinData(JoinData customJoinData)
{
_data = customJoinData;
}
public string GetNameAttribute(MemberInfo memberInfo)
{
var name = string.Empty;
var attribute = (JoinNameAttribute)CAttribute.GetCustomAttribute(memberInfo, typeof(JoinNameAttribute));
if (attribute == null) return name;
name = attribute.Name;
Debug.Console(2, "JoinName Attribute value: {0}", name);
return name;
/// Attempts to get the serialized join map from config
/// </summary>
/// <param name="joinMapKey"></param>
/// <returns></returns>
public static string GetSerializedJoinMapForDevice(string joinMapKey)
{
if (string.IsNullOrEmpty(joinMapKey))
return null;
var joinMap = ConfigReader.ConfigObject.JoinMaps[joinMapKey];
return joinMap;
}
/// <summary>
/// Attempts to get the serialized join map from config
/// </summary>
/// <param name="joinMapKey"></param>
/// <returns></returns>
public static string GetJoinMapForDevice(string joinMapKey)
{
return GetSerializedJoinMapForDevice(joinMapKey);
}
/// <summary>
/// Attempts to find a custom join map by key and returns it deserialized if found
/// </summary>
/// <param name="joinMapKey"></param>
/// <returns></returns>
public static Dictionary<string, JoinData> TryGetJoinMapAdvancedForDevice(string joinMapKey)
{
if (string.IsNullOrEmpty(joinMapKey))
return null;
var joinMapSerialzed = ConfigReader.ConfigObject.JoinMaps[joinMapKey];
if (joinMapSerialzed == null) return null;
var joinMapData = JsonConvert.DeserializeObject<Dictionary<string, JoinData>>(joinMapSerialzed);
return joinMapData;
}
}
/// <summary>
/// Base class for join maps
/// </summary>
[Obsolete("This is being deprecated in favor of JoinMapBaseAdvanced")]
public abstract class JoinMapBase
{
/// <summary>
/// Modifies all the join numbers by adding the offset. This should never be called twice
/// </summary>
/// <param name="joinStart"></param>
public abstract void OffsetJoinNumbers(uint joinStart);
/// <summary>
/// The collection of joins and associated metadata
/// </summary>
public Dictionary<string, JoinMetadata> Joins = new Dictionary<string, JoinMetadata>();
/// <summary>
/// Prints the join information to console
/// </summary>
public void PrintJoinMapInfo()
{
Debug.Console(0, "{0}:\n", GetType().Name);
// Get the joins of each type and print them
Debug.Console(0, "Digitals:");
var digitals = Joins.Where(j => (j.Value.JoinType & eJoinType.Digital) == eJoinType.Digital).ToDictionary(j => j.Key, j => j.Value);
Debug.Console(2, "Found {0} Digital Joins", digitals.Count);
PrintJoinList(GetSortedJoins(digitals));
Debug.Console(0, "Analogs:");
var analogs = Joins.Where(j => (j.Value.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value);
Debug.Console(2, "Found {0} Analog Joins", analogs.Count);
PrintJoinList(GetSortedJoins(analogs));
Debug.Console(0, "Serials:");
var serials = Joins.Where(j => (j.Value.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value);
Debug.Console(2, "Found {0} Serial Joins", serials.Count);
PrintJoinList(GetSortedJoins(serials));
}
/// <summary>
/// Returns a sorted list by JoinNumber
/// </summary>
/// <param name="joins"></param>
/// <returns></returns>
List<KeyValuePair<string, JoinMetadata>> GetSortedJoins(Dictionary<string, JoinMetadata> joins)
{
var sortedJoins = joins.ToList();
sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber));
return sortedJoins;
}
void PrintJoinList(List<KeyValuePair<string, JoinMetadata>> joins)
{
foreach (var join in joins)
{
Debug.Console(0,
@"Join Number: {0} | Label: '{1}' | JoinSpan: '{2}' | Type: '{3}' | Capabilities: '{4}'",
join.Value.JoinNumber,
join.Value.Label,
join.Value.JoinSpan,
join.Value.JoinType.ToString(),
join.Value.JoinCapabilities.ToString());
}
}
/// <summary>
/// Returns the join number for the join with the specified key
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public uint GetJoinForKey(string key)
{
return Joins.ContainsKey(key) ? Joins[key].JoinNumber : 0;
}
/// <summary>
/// Returns the join span for the join with the specified key
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public uint GetJoinSpanForKey(string key)
{
return Joins.ContainsKey(key) ? Joins[key].JoinSpan : 0;
}
}
[AttributeUsage(AttributeTargets.All)]
public class JoinNameAttribute : CAttribute
{
private string _Name;
public JoinNameAttribute(string name)
{
Debug.Console(2, "Setting Attribute Name: {0}", name);
_Name = name;
}
public string Name
{
get { return _Name; }
}
/// <summary>
/// Base class for join maps
/// </summary>
public abstract class JoinMapBaseAdvanced
{
protected uint JoinOffset;
/// <summary>
/// The collection of joins and associated metadata
/// </summary>
public Dictionary<string, JoinDataComplete> Joins { get; private set; }
protected JoinMapBaseAdvanced(uint joinStart)
{
Joins = new Dictionary<string, JoinDataComplete>();
JoinOffset = joinStart - 1;
}
protected JoinMapBaseAdvanced(uint joinStart, Type type):this(joinStart)
{
AddJoins(type);
}
protected void AddJoins(Type type)
{
// Add all the JoinDataComplete properties to the Joins Dictionary and pass in the offset
//Joins = this.GetType()
// .GetCType()
// .GetFields(BindingFlags.Public | BindingFlags.Instance)
// .Where(field => field.IsDefined(typeof(JoinNameAttribute), true))
// .Select(field => (JoinDataComplete)field.GetValue(this))
// .ToDictionary(join => join.GetNameAttribute(), join =>
// {
// join.SetJoinOffset(_joinOffset);
// return join;
// });
//type = this.GetType(); <- this wasn't working because 'this' was always the base class, never the derived class
var fields =
type.GetCType()
.GetFields(BindingFlags.Public | BindingFlags.Instance)
.Where(f => f.IsDefined(typeof (JoinNameAttribute), true));
foreach (var field in fields)
{
var childClass = Convert.ChangeType(this, type, null);
var value = field.GetValue(childClass) as JoinDataComplete; //this here is JoinMapBaseAdvanced, not the child class. JoinMapBaseAdvanced has no fields.
if (value == null)
{
Debug.Console(0, "Unable to caset base class to {0}", type.Name);
continue;
}
value.SetJoinOffset(JoinOffset);
var joinName = value.GetNameAttribute(field);
if (String.IsNullOrEmpty(joinName)) continue;
Joins.Add(joinName, value);
}
PrintJoinMapInfo();
}
/// <summary>
/// Prints the join information to console
/// </summary>
public void PrintJoinMapInfo()
{
Debug.Console(0, "{0}:\n", GetType().Name);
// Get the joins of each type and print them
Debug.Console(0, "Digitals:");
var digitals = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Digital) == eJoinType.Digital).ToDictionary(j => j.Key, j => j.Value);
Debug.Console(2, "Found {0} Digital Joins", digitals.Count);
PrintJoinList(GetSortedJoins(digitals));
Debug.Console(0, "Analogs:");
var analogs = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value);
Debug.Console(2, "Found {0} Analog Joins", analogs.Count);
PrintJoinList(GetSortedJoins(analogs));
Debug.Console(0, "Serials:");
var serials = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value);
Debug.Console(2, "Found {0} Serial Joins", serials.Count);
PrintJoinList(GetSortedJoins(serials));
}
/// <summary>
/// Returns a sorted list by JoinNumber
/// </summary>
/// <param name="joins"></param>
/// <returns></returns>
List<KeyValuePair<string, JoinDataComplete>> GetSortedJoins(Dictionary<string, JoinDataComplete> joins)
{
var sortedJoins = joins.ToList();
sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber));
return sortedJoins;
}
void PrintJoinList(List<KeyValuePair<string, JoinDataComplete>> joins)
{
foreach (var join in joins)
{
Debug.Console(0,
@"Join Number: {0} | JoinSpan: '{1}' | Label: '{2}' | Type: '{3}' | Capabilities: '{4}'",
join.Value.JoinNumber,
join.Value.JoinSpan,
join.Value.Metadata.Label,
join.Value.Metadata.JoinType.ToString(),
join.Value.Metadata.JoinCapabilities.ToString());
}
}
/// <summary>
/// Attempts to find the matching key for the custom join and if found overwrites the default JoinData with the custom
/// </summary>
/// <param name="joinData"></param>
public void SetCustomJoinData(Dictionary<string, JoinData> joinData)
{
foreach (var customJoinData in joinData)
{
var join = Joins[customJoinData.Key];
if (join != null)
{
join.SetCustomJoinData(customJoinData.Value);
}
else
{
Debug.Console(2, "No mathcing key found in join map for: '{0}'", customJoinData.Key);
}
}
PrintJoinMapInfo();
}
///// <summary>
///// Returns the join number for the join with the specified key
///// </summary>
///// <param name="key"></param>
///// <returns></returns>
//public uint GetJoinForKey(string key)
//{
// return Joins.ContainsKey(key) ? Joins[key].JoinNumber : 0;
//}
///// <summary>
///// Returns the join span for the join with the specified key
///// </summary>
///// <param name="key"></param>
///// <returns></returns>
//public uint GetJoinSpanForKey(string key)
//{
// return Joins.ContainsKey(key) ? Joins[key].JoinSpan : 0;
//}
}
/// <summary>
/// Read = Provides feedback to SIMPL
/// Write = Responds to sig values from SIMPL
/// </summary>
[Flags]
public enum eJoinCapabilities
{
None = 0,
ToSIMPL = 1,
FromSIMPL = 2,
ToFromSIMPL = ToSIMPL | FromSIMPL
}
[Flags]
public enum eJoinType
{
None = 0,
Digital = 1,
Analog = 2,
Serial = 4,
DigitalAnalog = Digital | Analog,
DigitalSerial = Digital | Serial,
AnalogSerial = Analog | Serial,
DigitalAnalogSerial = Digital | Analog | Serial
}
/// <summary>
/// Metadata describing the join
/// </summary>
public class JoinMetadata
{
private string _description;
/// <summary>
/// Join number (based on join offset value)
/// </summary>
[JsonProperty("joinNumber")]
[Obsolete]
public uint JoinNumber { get; set; }
/// <summary>
/// Join range span. If join indicates the start of a range of joins, this indicated the maximum number of joins in the range
/// </summary>
[Obsolete]
[JsonProperty("joinSpan")]
public uint JoinSpan { get; set; }
/// <summary>
/// A label for the join to better describe its usage
/// </summary>
[Obsolete("Use Description instead")]
[JsonProperty("label")]
public string Label { get { return _description; } set { _description = value; } }
/// <summary>
/// A description for the join to better describe its usage
/// </summary>
[JsonProperty("description")]
public string Description { get { return _description; } set { _description = value; } }
/// <summary>
/// Signal type(s)
/// </summary>
[JsonProperty("joinType")]
public eJoinType JoinType { get; set; }
/// <summary>
/// Indicates whether the join is read and/or write
/// </summary>
[JsonProperty("joinCapabilities")]
public eJoinCapabilities JoinCapabilities { get; set; }
/// <summary>
/// Indicates a set of valid values (particularly if this translates to an enum
/// </summary>
[JsonProperty("validValues")]
public string[] ValidValues { get; set; }
}
/// <summary>
/// Data describing the join. Can be
/// </summary>
public class JoinData
{
/// <summary>
/// Join number (based on join offset value)
/// </summary>
[JsonProperty("joinNumber")]
public uint JoinNumber { get; set; }
/// <summary>
/// Join range span. If join indicates the start of a range of joins, this indicated the maximum number of joins in the range
/// </summary>
[JsonProperty("joinSpan")]
public uint JoinSpan { get; set; }
}
/// <summary>
/// A class to aggregate the JoinData and JoinMetadata for a join
/// </summary>
public class JoinDataComplete
{
private uint _joinOffset;
private JoinData _data;
public JoinMetadata Metadata { get; set; }
public JoinDataComplete(JoinData data, JoinMetadata metadata)
{
_data = data;
Metadata = metadata;
}
/// <summary>
/// Sets the join offset value
/// </summary>
/// <param name="joinOffset"></param>
public void SetJoinOffset(uint joinOffset)
{
_joinOffset = joinOffset;
}
/// <summary>
/// The join number (including the offset)
/// </summary>
public uint JoinNumber
{
get { return _data.JoinNumber+ _joinOffset; }
set { _data.JoinNumber = value; }
}
public uint JoinSpan
{
get { return _data.JoinSpan; }
}
public void SetCustomJoinData(JoinData customJoinData)
{
_data = customJoinData;
}
public string GetNameAttribute(MemberInfo memberInfo)
{
var name = string.Empty;
var attribute = (JoinNameAttribute)CAttribute.GetCustomAttribute(memberInfo, typeof(JoinNameAttribute));
if (attribute == null) return name;
name = attribute.Name;
Debug.Console(2, "JoinName Attribute value: {0}", name);
return name;
}
}
[AttributeUsage(AttributeTargets.All)]
public class JoinNameAttribute : CAttribute
{
private string _Name;
public JoinNameAttribute(string name)
{
Debug.Console(2, "Setting Attribute Name: {0}", name);
_Name = name;
}
public string Name
{
get { return _Name; }
}
}
}

View File

@@ -11,7 +11,7 @@ using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Devices.Common.Occupancy
namespace PepperDash.Essentials.Core
{
[Description("Wrapper class for CEN-ODT-C-POE")]
public class CenOdtOccupancySensorBaseController : CrestronGenericBridgeableBaseDevice, IOccupancyStatusProvider

View File

@@ -11,7 +11,7 @@ using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Devices.Common.Occupancy
namespace PepperDash.Essentials.Core
{
[Description("Wrapper class for Single Technology GLS Occupancy Sensors")]
public class GlsOccupancySensorBaseController : CrestronGenericBridgeableBaseDevice, IOccupancyStatusProvider
@@ -55,11 +55,29 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy
}
}
public GlsOccupancySensorBaseController(string key, string name, GlsOccupancySensorBase sensor)
: base(key, name, sensor)
public GlsOccupancySensorBaseController(string key, Func<DeviceConfig, GlsOccupancySensorBase> preActivationFunc,
DeviceConfig config)
: base(key, config.Name)
{
OccSensor = sensor;
AddPreActivationAction(() =>
{
OccSensor = preActivationFunc(config);
RegisterCrestronGenericBase(OccSensor);
RegisterGlsOdtSensorBaseController(OccSensor);
});
}
public GlsOccupancySensorBaseController(string key, string name) : base(key, name) {}
protected void RegisterGlsOdtSensorBaseController(GlsOccupancySensorBase occSensor)
{
OccSensor = occSensor;
RoomIsOccupiedFeedback = new BoolFeedback(RoomIsOccupiedFeedbackFunc);
PirSensorEnabledFeedback = new BoolFeedback(() => OccSensor.PirEnabledFeedback.BoolValue);
@@ -68,15 +86,18 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy
ShortTimeoutEnabledFeedback = new BoolFeedback(() => OccSensor.ShortTimeoutEnabledFeedback.BoolValue);
PirSensitivityInVacantStateFeedback = new IntFeedback(() => OccSensor.PirSensitivityInVacantStateFeedback.UShortValue);
PirSensitivityInVacantStateFeedback =
new IntFeedback(() => OccSensor.PirSensitivityInVacantStateFeedback.UShortValue);
PirSensitivityInOccupiedStateFeedback = new IntFeedback(() => OccSensor.PirSensitivityInOccupiedStateFeedback.UShortValue);
PirSensitivityInOccupiedStateFeedback =
new IntFeedback(() => OccSensor.PirSensitivityInOccupiedStateFeedback.UShortValue);
CurrentTimeoutFeedback = new IntFeedback(() => OccSensor.CurrentTimeoutFeedback.UShortValue);
LocalTimoutFeedback = new IntFeedback(() => OccSensor.LocalTimeoutFeedback.UShortValue);
GraceOccupancyDetectedFeedback = new BoolFeedback(() => OccSensor.GraceOccupancyDetectedFeedback.BoolValue);
GraceOccupancyDetectedFeedback =
new BoolFeedback(() => OccSensor.GraceOccupancyDetectedFeedback.BoolValue);
RawOccupancyFeedback = new BoolFeedback(() => OccSensor.RawOccupancyFeedback.BoolValue);
@@ -84,9 +105,9 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy
ExternalPhotoSensorValue = new IntFeedback(() => OccSensor.ExternalPhotoSensorValueFeedback.UShortValue);
OccSensor.BaseEvent += new Crestron.SimplSharpPro.BaseEventHandler(OccSensor_BaseEvent);
OccSensor.BaseEvent += OccSensor_BaseEvent;
OccSensor.GlsOccupancySensorChange += new GlsOccupancySensorChangeEventHandler(OccSensor_GlsOccupancySensorChange);
OccSensor.GlsOccupancySensorChange += OccSensor_GlsOccupancySensorChange;
}
@@ -97,40 +118,56 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy
/// <param name="args"></param>
protected virtual void OccSensor_GlsOccupancySensorChange(GlsOccupancySensorBase device, GlsOccupancySensorChangeEventArgs args)
{
if (args.EventId == GlsOccupancySensorBase.PirEnabledFeedbackEventId)
PirSensorEnabledFeedback.FireUpdate();
else if (args.EventId == GlsOccupancySensorBase.LedFlashEnabledFeedbackEventId)
LedFlashEnabledFeedback.FireUpdate();
else if (args.EventId == GlsOccupancySensorBase.ShortTimeoutEnabledFeedbackEventId)
ShortTimeoutEnabledFeedback.FireUpdate();
else if (args.EventId == GlsOccupancySensorBase.PirSensitivityInOccupiedStateFeedbackEventId)
PirSensitivityInOccupiedStateFeedback.FireUpdate();
else if (args.EventId == GlsOccupancySensorBase.PirSensitivityInVacantStateFeedbackEventId)
PirSensitivityInVacantStateFeedback.FireUpdate();
switch (args.EventId)
{
case GlsOccupancySensorBase.PirEnabledFeedbackEventId:
PirSensorEnabledFeedback.FireUpdate();
break;
case GlsOccupancySensorBase.LedFlashEnabledFeedbackEventId:
LedFlashEnabledFeedback.FireUpdate();
break;
case GlsOccupancySensorBase.ShortTimeoutEnabledFeedbackEventId:
ShortTimeoutEnabledFeedback.FireUpdate();
break;
case GlsOccupancySensorBase.PirSensitivityInOccupiedStateFeedbackEventId:
PirSensitivityInOccupiedStateFeedback.FireUpdate();
break;
case GlsOccupancySensorBase.PirSensitivityInVacantStateFeedbackEventId:
PirSensitivityInVacantStateFeedback.FireUpdate();
break;
}
}
protected virtual void OccSensor_BaseEvent(Crestron.SimplSharpPro.GenericBase device, Crestron.SimplSharpPro.BaseEventArgs args)
{
Debug.Console(2, this, "GlsOccupancySensorChange EventId: {0}", args.EventId);
if (args.EventId == Crestron.SimplSharpPro.GeneralIO.GlsOccupancySensorBase.RoomOccupiedFeedbackEventId
|| args.EventId == Crestron.SimplSharpPro.GeneralIO.GlsOccupancySensorBase.RoomVacantFeedbackEventId)
switch (args.EventId)
{
Debug.Console(1, this, "Occupancy State: {0}", OccSensor.OccupancyDetectedFeedback.BoolValue);
RoomIsOccupiedFeedback.FireUpdate();
case Crestron.SimplSharpPro.GeneralIO.GlsOccupancySensorBase.RoomVacantFeedbackEventId:
case Crestron.SimplSharpPro.GeneralIO.GlsOccupancySensorBase.RoomOccupiedFeedbackEventId:
Debug.Console(1, this, "Occupancy State: {0}", OccSensor.OccupancyDetectedFeedback.BoolValue);
RoomIsOccupiedFeedback.FireUpdate();
break;
case GlsOccupancySensorBase.TimeoutFeedbackEventId:
CurrentTimeoutFeedback.FireUpdate();
break;
case GlsOccupancySensorBase.TimeoutLocalFeedbackEventId:
LocalTimoutFeedback.FireUpdate();
break;
case GlsOccupancySensorBase.GraceOccupancyDetectedFeedbackEventId:
GraceOccupancyDetectedFeedback.FireUpdate();
break;
case GlsOccupancySensorBase.RawOccupancyFeedbackEventId:
RawOccupancyFeedback.FireUpdate();
break;
case GlsOccupancySensorBase.InternalPhotoSensorValueFeedbackEventId:
InternalPhotoSensorValue.FireUpdate();
break;
case GlsOccupancySensorBase.ExternalPhotoSensorValueFeedbackEventId:
ExternalPhotoSensorValue.FireUpdate();
break;
}
else if (args.EventId == GlsOccupancySensorBase.TimeoutFeedbackEventId)
CurrentTimeoutFeedback.FireUpdate();
else if (args.EventId == GlsOccupancySensorBase.TimeoutLocalFeedbackEventId)
LocalTimoutFeedback.FireUpdate();
else if (args.EventId == GlsOccupancySensorBase.GraceOccupancyDetectedFeedbackEventId)
GraceOccupancyDetectedFeedback.FireUpdate();
else if (args.EventId == GlsOccupancySensorBase.RawOccupancyFeedbackEventId)
RawOccupancyFeedback.FireUpdate();
else if (args.EventId == GlsOccupancySensorBase.InternalPhotoSensorValueFeedbackEventId)
InternalPhotoSensorValue.FireUpdate();
else if (args.EventId == GlsOccupancySensorBase.ExternalPhotoSensorValueFeedbackEventId)
ExternalPhotoSensorValue.FireUpdate();
}
public void SetTestMode(bool mode)
@@ -373,27 +410,51 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy
{
LinkOccSensorToApi(this, trilist, joinStart, joinMapKey, bridge);
}
}
public class GlsOccupancySensorBaseControllerFactory : EssentialsDeviceFactory<GlsOccupancySensorBaseController>
{
public GlsOccupancySensorBaseControllerFactory()
#region PreActivation
private static GlsOirCCn GetGlsOirCCn(DeviceConfig dc)
{
TypeNames = new List<string>() { "glsoirccn" };
var control = CommFactory.GetControlPropertiesConfig(dc);
var cresnetId = control.CresnetIdInt;
var branchId = control.ControlPortNumber;
var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey;
if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase))
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new GlsOirCCn", parentKey);
return new GlsOirCCn(cresnetId, Global.ControlSystem);
}
var cresnetBridge = DeviceManager.GetDeviceForKey(parentKey) as IHasCresnetBranches;
if (cresnetBridge != null)
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new GlsOirCCn", parentKey);
return new GlsOirCCn(cresnetId, cresnetBridge.CresnetBranches[branchId]);
}
Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey);
return null;
}
#endregion
public override EssentialsDevice BuildDevice(DeviceConfig dc)
public class GlsOccupancySensorBaseControllerFactory : EssentialsDeviceFactory<GlsOccupancySensorBaseController>
{
Debug.Console(1, "Factory Attempting to create new GlsOccupancySensorBaseController Device");
public GlsOccupancySensorBaseControllerFactory()
{
TypeNames = new List<string>() { "glsoirccn" };
}
var key = dc.Key;
var name = dc.Name;
var comm = CommFactory.GetControlPropertiesConfig(dc);
GlsOccupancySensorBase occSensor = new GlsOirCCn(comm.CresnetIdInt, Global.ControlSystem);
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new GlsOccupancySensorBaseController Device");
return new GlsOccupancySensorBaseController(dc.Key, GetGlsOirCCn, dc);
}
return new GlsOccupancySensorBaseController(key, name, occSensor);
}
}
}

View File

@@ -11,7 +11,7 @@ using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Devices.Common.Occupancy
namespace PepperDash.Essentials.Core
{
[Description("Wrapper class for Dual Technology GLS Occupancy Sensors")]
public class GlsOdtOccupancySensorController : GlsOccupancySensorBaseController
@@ -35,26 +35,35 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy
public BoolFeedback RawOccupancyUsFeedback { get; private set; }
public GlsOdtOccupancySensorController(string key, string name, GlsOdtCCn sensor)
: base(key, name, sensor)
public GlsOdtOccupancySensorController(string key, Func<DeviceConfig, GlsOdtCCn> preActivationFunc,
DeviceConfig config)
: base(key, config.Name)
{
OccSensor = sensor;
AddPreActivationAction(() =>
{
OccSensor = preActivationFunc(config);
AndWhenVacatedFeedback = new BoolFeedback(() => OccSensor.AndWhenVacatedFeedback.BoolValue);
RegisterCrestronGenericBase(OccSensor);
OrWhenVacatedFeedback = new BoolFeedback(() => OccSensor.OrWhenVacatedFeedback.BoolValue);
RegisterGlsOdtSensorBaseController(OccSensor);
UltrasonicAEnabledFeedback = new BoolFeedback(() => OccSensor.UsAEnabledFeedback.BoolValue);
AndWhenVacatedFeedback = new BoolFeedback(() => OccSensor.AndWhenVacatedFeedback.BoolValue);
UltrasonicBEnabledFeedback = new BoolFeedback(() => OccSensor.UsBEnabledFeedback.BoolValue);
OrWhenVacatedFeedback = new BoolFeedback(() => OccSensor.OrWhenVacatedFeedback.BoolValue);
RawOccupancyPirFeedback = new BoolFeedback(() => OccSensor.RawOccupancyPirFeedback.BoolValue);
UltrasonicAEnabledFeedback = new BoolFeedback(() => OccSensor.UsAEnabledFeedback.BoolValue);
RawOccupancyUsFeedback = new BoolFeedback(() => OccSensor.RawOccupancyUsFeedback.BoolValue);
UltrasonicBEnabledFeedback = new BoolFeedback(() => OccSensor.UsBEnabledFeedback.BoolValue);
UltrasonicSensitivityInVacantStateFeedback = new IntFeedback(() => OccSensor.UsSensitivityInVacantStateFeedback.UShortValue);
RawOccupancyPirFeedback = new BoolFeedback(() => OccSensor.RawOccupancyPirFeedback.BoolValue);
UltrasonicSensitivityInOccupiedStateFeedback = new IntFeedback(() => OccSensor.UsSensitivityInOccupiedStateFeedback.UShortValue);
RawOccupancyUsFeedback = new BoolFeedback(() => OccSensor.RawOccupancyUsFeedback.BoolValue);
UltrasonicSensitivityInVacantStateFeedback = new IntFeedback(() => OccSensor.UsSensitivityInVacantStateFeedback.UShortValue);
UltrasonicSensitivityInOccupiedStateFeedback = new IntFeedback(() => OccSensor.UsSensitivityInOccupiedStateFeedback.UShortValue);
});
}
/// <summary>
@@ -160,38 +169,51 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy
{
LinkOccSensorToApi(this, trilist, joinStart, joinMapKey, bridge);
}
}
public class GlsOdtOccupancySensorControllerFactory : EssentialsDeviceFactory<GlsOdtOccupancySensorController>
{
public GlsOdtOccupancySensorControllerFactory()
#region PreActivation
private static GlsOdtCCn GetGlsOdtCCn(DeviceConfig dc)
{
TypeNames = new List<string>() { "glsodtccn" };
}
var control = CommFactory.GetControlPropertiesConfig(dc);
var cresnetId = control.CresnetIdInt;
var branchId = control.ControlPortNumber;
var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey;
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new GlsOccupancySensorBaseController Device");
var typeName = dc.Type.ToLower();
var key = dc.Key;
var name = dc.Name;
var comm = CommFactory.GetControlPropertiesConfig(dc);
var occSensor = new GlsOdtCCn(comm.CresnetIdInt, Global.ControlSystem);
if (occSensor != null)
if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase))
{
return new GlsOdtOccupancySensorController(key, name, occSensor);
Debug.Console(0, "Device {0} is a valid cresnet master - creating new GlsOdtCCn", parentKey);
return new GlsOdtCCn(cresnetId, Global.ControlSystem);
}
else
var cresnetBridge = DeviceManager.GetDeviceForKey(parentKey) as IHasCresnetBranches;
if (cresnetBridge != null)
{
Debug.Console(0, "ERROR: Unable to create Occupancy Sensor Device. Key: '{0}'", key);
return null;
Debug.Console(0, "Device {0} is a valid cresnet master - creating new GlsOdtCCn", parentKey);
return new GlsOdtCCn(cresnetId, cresnetBridge.CresnetBranches[branchId]);
}
Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey);
return null;
}
#endregion
public class GlsOdtOccupancySensorControllerFactory : EssentialsDeviceFactory<GlsOdtOccupancySensorController>
{
public GlsOdtOccupancySensorControllerFactory()
{
TypeNames = new List<string>() { "glsodtccn" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new GlsOccupancySensorBaseController Device");
return new GlsOdtOccupancySensorController(dc.Key, GetGlsOdtCCn, dc);
}
}
}
}

View File

@@ -5,9 +5,9 @@ using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Occupancy
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Aggregates the RoomIsOccupied feedbacks of one or more IOccupancyStatusProvider objects

View File

@@ -0,0 +1,280 @@
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.GeneralIO;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash_Essentials_Core.Bridges.JoinMaps;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.Gateways;
using Newtonsoft.Json;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash_Essentials_Core;
namespace PepperDash.Essentials.Core
{
[Description("Wrapper class for GLS Cresnet Partition Sensor")]
public class GlsPartitionSensorController : CrestronGenericBridgeableBaseDevice
{
private GlsPartCn _partitionSensor;
public StringFeedback NameFeedback { get; private set; }
public BoolFeedback EnableFeedback { get; private set; }
public BoolFeedback PartitionSensedFeedback { get; private set; }
public BoolFeedback PartitionNotSensedFeedback { get; private set; }
public IntFeedback SensitivityFeedback { get; private set; }
public bool InTestMode { get; private set; }
public bool TestEnableFeedback { get; private set; }
public bool TestPartitionSensedFeedback { get; private set; }
public int TestSensitivityFeedback { get; private set; }
public GlsPartitionSensorController(string key, Func<DeviceConfig, GlsPartCn> preActivationFunc, DeviceConfig config)
: base(key, config.Name)
{
AddPreActivationAction(() =>
{
_partitionSensor = preActivationFunc(config);
RegisterCrestronGenericBase(_partitionSensor);
NameFeedback = new StringFeedback(() => Name);
EnableFeedback = new BoolFeedback(() => _partitionSensor.EnableFeedback.BoolValue);
PartitionSensedFeedback = new BoolFeedback(() => _partitionSensor.PartitionSensedFeedback.BoolValue);
PartitionNotSensedFeedback = new BoolFeedback(() => _partitionSensor.PartitionNotSensedFeedback.BoolValue);
SensitivityFeedback = new IntFeedback(() => _partitionSensor.SensitivityFeedback.UShortValue);
if (_partitionSensor != null) _partitionSensor.BaseEvent += PartitionSensor_BaseEvent;
});
}
private void PartitionSensor_BaseEvent(GenericBase device, BaseEventArgs args)
{
Debug.Console(2, this, "EventId: {0}, Index: {1}", args.EventId, args.Index);
switch (args.EventId)
{
case (GlsPartCn.EnableFeedbackEventId):
{
EnableFeedback.FireUpdate();
break;
}
case (GlsPartCn.PartitionSensedFeedbackEventId):
{
PartitionSensedFeedback.FireUpdate();
break;
}
case (GlsPartCn.PartitionNotSensedFeedbackEventId):
{
PartitionNotSensedFeedback.FireUpdate();
break;
}
case (GlsPartCn.SensitivityFeedbackEventId):
{
SensitivityFeedback.FireUpdate();
break;
}
default:
{
Debug.Console(2, this, "Unhandled args.EventId: {0}", args.EventId);
break;
}
}
}
public void SetTestMode(bool mode)
{
InTestMode = mode;
Debug.Console(1, this, "InTestMode: {0}", InTestMode.ToString());
}
public void SetTestEnableState(bool state)
{
if (InTestMode)
{
TestEnableFeedback = state;
Debug.Console(1, this, "TestEnableFeedback: {0}", TestEnableFeedback.ToString());
return;
}
Debug.Console(1, this, "InTestMode: {0}, unable to set enable state: {1}", InTestMode.ToString(), state.ToString());
}
public void SetTestPartitionSensedState(bool state)
{
if (InTestMode)
{
TestPartitionSensedFeedback = state;
Debug.Console(1, this, "TestPartitionSensedFeedback: {0}", TestPartitionSensedFeedback.ToString());
return;
}
Debug.Console(1, this, "InTestMode: {0}, unable to set partition state: {1}", InTestMode.ToString(), state.ToString());
}
public void SetTestSensitivityValue(int value)
{
if (InTestMode)
{
TestSensitivityFeedback = value;
Debug.Console(1, this, "TestSensitivityFeedback: {0}", TestSensitivityFeedback);
return;
}
Debug.Console(1, this, "InTestMode: {0}, unable to set sensitivity value: {1}", InTestMode.ToString(), value);
}
public void SetEnableState(bool state)
{
if (_partitionSensor == null)
return;
_partitionSensor.Enable.BoolValue = state;
}
public void IncreaseSensitivity()
{
if (_partitionSensor == null)
return;
_partitionSensor.IncreaseSensitivity();
}
public void DecreaseSensitivity()
{
if (_partitionSensor == null)
return;
_partitionSensor.DecreaseSensitivity();
}
public void SetSensitivity(ushort value)
{
if (_partitionSensor == null)
return;
_partitionSensor.Sensitivity.UShortValue = value;
}
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new GlsPartitionSensorJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GlsPartitionSensorJoinMap>(joinMapSerialized);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.Console(0, this, "Please update config to use 'type': 'EiscApiAdvanced' to get all join map features for this device");
}
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, this, "Linking to Bridge Type {0}", GetType().Name);
// link input from simpl
trilist.SetSigTrueAction(joinMap.Enable.JoinNumber, () => SetEnableState(true));
trilist.SetSigFalseAction(joinMap.Enable.JoinNumber, () => SetEnableState(false));
trilist.SetSigTrueAction(joinMap.IncreaseSensitivity.JoinNumber, IncreaseSensitivity);
trilist.SetSigTrueAction(joinMap.DecreaseSensitivity.JoinNumber, DecreaseSensitivity);
trilist.SetUShortSigAction(joinMap.Sensitivity.JoinNumber, SetSensitivity);
// link output to simpl
IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
EnableFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Enable.JoinNumber]);
PartitionSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionSensed.JoinNumber]);
PartitionNotSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionNotSensed.JoinNumber]);
SensitivityFeedback.LinkInputSig(trilist.UShortInput[joinMap.Sensitivity.JoinNumber]);
FeedbacksFireUpdates();
// update when device is online
_partitionSensor.OnlineStatusChange += (o, a) =>
{
if (a.DeviceOnLine)
{
FeedbacksFireUpdates();
}
};
// update when trilist is online
trilist.OnlineStatusChange += (o, a) =>
{
if (a.DeviceOnLine)
{
FeedbacksFireUpdates();
}
};
}
private void FeedbacksFireUpdates()
{
IsOnline.FireUpdate();
NameFeedback.FireUpdate();
EnableFeedback.FireUpdate();
PartitionSensedFeedback.FireUpdate();
PartitionNotSensedFeedback.FireUpdate();
SensitivityFeedback.FireUpdate();
}
#region PreActivation
private static GlsPartCn GetGlsPartCnDevice(DeviceConfig dc)
{
var control = CommFactory.GetControlPropertiesConfig(dc);
var cresnetId = control.CresnetIdInt;
var branchId = control.ControlPortNumber;
var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey;
if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase))
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new GlsPartCn", parentKey);
return new GlsPartCn(cresnetId, Global.ControlSystem);
}
var cresnetBridge = DeviceManager.GetDeviceForKey(parentKey) as IHasCresnetBranches;
if (cresnetBridge != null)
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new GlsPartCn", parentKey);
return new GlsPartCn(cresnetId, cresnetBridge.CresnetBranches[branchId]);
}
Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey);
return null;
}
#endregion
public class GlsPartitionSensorControllerFactory : EssentialsDeviceFactory<GlsPartitionSensorController>
{
public GlsPartitionSensorControllerFactory()
{
TypeNames = new List<string>() { "glspartcn" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device");
return new GlsPartitionSensorController(dc.Key, GetGlsPartCnDevice, dc);
}
}
}
}

View File

@@ -64,7 +64,7 @@
</Reference>
<Reference Include="Crestron.SimplSharpPro.Gateways, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll</HintPath>
<HintPath>..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll</HintPath>
</Reference>
<Reference Include="Crestron.SimplSharpPro.GeneralIO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -137,6 +137,7 @@
<Compile Include="Bridges\JoinMaps\GenericLightingJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\GenericRelayControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\GlsOccupancySensorBaseJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\GlsPartitionSensorJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\HdMdNxM4kEControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\HdMdxxxCEControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\Hrxxx0WirelessRemoteControllerJoinMap.cs" />
@@ -171,6 +172,8 @@
</Compile>
<Compile Include="Crestron IO\Cards\CenCi33Controller.cs" />
<Compile Include="Crestron IO\Cards\InternalCardCageController.cs" />
<Compile Include="Crestron IO\DinCenCn\DinCenCnController.cs" />
<Compile Include="Crestron IO\DinCenCn\IHasCresnetBranches.cs" />
<Compile Include="Crestron IO\Inputs\CenIoDigIn104Controller.cs" />
<Compile Include="Crestron IO\Inputs\GenericDigitalInputDevice.cs" />
<Compile Include="Crestron IO\Inputs\GenericVersiportInputDevice.cs" />
@@ -179,40 +182,20 @@
<Compile Include="Crestron IO\Relay\GenericRelayDevice.cs" />
<Compile Include="Crestron IO\Relay\ISwitchedOutput.cs" />
<Compile Include="Crestron IO\StatusSign\StatusSignController.cs" />
<Compile Include="Devices\Base Classes\AudioCodecBase.cs" />
<Compile Include="Devices\Interfaces\CodecInterfaces.cs" />
<Compile Include="Devices\CodecInterfaces.cs" />
<Compile Include="Devices\CrestronProcessor.cs" />
<Compile Include="Devices\DestinationListItem.cs" />
<Compile Include="Devices\Base Classes\DeviceApiBase.cs" />
<Compile Include="Devices\DeviceApiBase.cs" />
<Compile Include="Devices\DeviceFeedbackExtensions.cs" />
<Compile Include="Devices\Base Classes\EssentialsBridgeableDevice.cs" />
<Compile Include="Devices\Base Classes\EssentialsDevice.cs" />
<Compile Include="Devices\Interfaces\IProjectorInterfaces.cs" />
<Compile Include="Devices\EssentialsBridgeableDevice.cs" />
<Compile Include="Devices\EssentialsDevice.cs" />
<Compile Include="Devices\IProjectorInterfaces.cs" />
<Compile Include="Devices\PC\InRoomPc.cs" />
<Compile Include="Devices\PC\Laptop.cs" />
<Compile Include="Devices\Base Classes\ReconfigurableDevice.cs" />
<Compile Include="Devices\Base Classes\VideoCodecBase.cs" />
<Compile Include="Devices\ReconfigurableDevice.cs" />
<Compile Include="Devices\VolumeDeviceChangeEventArgs.cs" />
<Compile Include="DeviceTypeInterfaces\Codec\CodecActiveCallItem.cs" />
<Compile Include="DeviceTypeInterfaces\Codec\eCodecCallDirection.cs" />
<Compile Include="DeviceTypeInterfaces\Codec\eCodecCallStatus.cs" />
<Compile Include="DeviceTypeInterfaces\Codec\eCodecCallType.cs" />
<Compile Include="DeviceTypeInterfaces\Codec\eMeetingPrivacy.cs" />
<Compile Include="DeviceTypeInterfaces\IAudioCodecInfo.cs" />
<Compile Include="DeviceTypeInterfaces\Codec\iCodecAudio.cs" />
<Compile Include="DeviceTypeInterfaces\IHasAudioCodec.cs" />
<Compile Include="DeviceTypeInterfaces\Codec\iHasCallFavorites.cs" />
<Compile Include="DeviceTypeInterfaces\Codec\iHasCallHistory.cs" />
<Compile Include="DeviceTypeInterfaces\IHasCodecLayouts.cs" />
<Compile Include="DeviceTypeInterfaces\IHasCodecSelfview.cs" />
<Compile Include="DeviceTypeInterfaces\Codec\iHasContentSharing.cs" />
<Compile Include="DeviceTypeInterfaces\Codec\iHasDialer.cs" />
<Compile Include="DeviceTypeInterfaces\Codec\iHasDirectory.cs" />
<Compile Include="DeviceTypeInterfaces\Codec\iHasScheduleAwareness.cs" />
<Compile Include="DeviceTypeInterfaces\IHasVideoCodec.cs" />
<Compile Include="DeviceTypeInterfaces\iVideoCodecInfo.cs" />
<Compile Include="Factory\DeviceFactory.cs" />
<Compile Include="Factory\IDeviceFactory.cs" />
<Compile Include="Factory\ReadyEventArgs.cs" />
<Compile Include="Feedbacks\BoolFeedback.cs" />
<Compile Include="Feedbacks\FeedbackCollection.cs" />
<Compile Include="Feedbacks\FeedbackEventArgs.cs" />
@@ -234,6 +217,11 @@
<Compile Include="Monitoring\SystemMonitorController.cs" />
<Compile Include="Microphone Privacy\MicrophonePrivacyController.cs" />
<Compile Include="Microphone Privacy\MicrophonePrivacyControllerConfig.cs" />
<Compile Include="Occupancy\CenOdtOccupancySensorBaseController.cs" />
<Compile Include="Occupancy\GlsOccupancySensorBaseController.cs" />
<Compile Include="Occupancy\GlsOdtOccupancySensorController.cs" />
<Compile Include="Occupancy\IOccupancyStatusProviderAggregator.cs" />
<Compile Include="PartitionSensor\GlsPartitionSensorController.cs" />
<Compile Include="Plugins\PluginLoader.cs" />
<Compile Include="Presets\PresetBase.cs" />
<Compile Include="Plugins\IPluginDeviceFactory.cs" />
@@ -243,8 +231,8 @@
<Compile Include="Config\InfoConfig.cs" />
<Compile Include="Config\DeviceConfig.cs" />
<Compile Include="Devices\DisplayUiConstants.cs" />
<Compile Include="Devices\Interfaces\IUsageTracking.cs" />
<Compile Include="Devices\Base Classes\DeviceJsonApi.cs" />
<Compile Include="Devices\IUsageTracking.cs" />
<Compile Include="Devices\DeviceJsonApi.cs" />
<Compile Include="Devices\SourceListItem.cs" />
<Compile Include="DeviceTypeInterfaces\IDisplayBasic.cs" />
<Compile Include="DeviceTypeInterfaces\IDumbSource.cs" />
@@ -261,7 +249,7 @@
<Compile Include="DeviceTypeInterfaces\ITransport.cs" />
<Compile Include="Devices\GenericMonitoredTcpDevice.cs" />
<Compile Include="DeviceTypeInterfaces\INumeric.cs" />
<Compile Include="Devices\Interfaces\IVolumeAndAudioInterfaces.cs" />
<Compile Include="Devices\IVolumeAndAudioInterfaces.cs" />
<Compile Include="Display\BasicIrDisplay.cs" />
<Compile Include="Feedbacks\BoolFeedbackOneShot.cs" />
<Compile Include="Ramps and Increments\NumericalHelpers.cs" />
@@ -269,24 +257,10 @@
<Compile Include="Remotes\ButtonExtensions.cs" />
<Compile Include="Remotes\CrestronRemotePropertiesConfig.cs" />
<Compile Include="Remotes\Hrxx0WirelessRemoteController.cs" />
<Compile Include="Rooms\Behaviours\RoomOnToDefaultSourceWhenOccupied.cs" />
<Compile Include="Rooms\Config\DDVC01RoomPropertiesConfig.cs" />
<Compile Include="Rooms\Config\EssentialsDualDisplayRoomPropertiesConfig.cs" />
<Compile Include="Rooms\Config\EssentialsHuddleRoomPropertiesConfig.cs" />
<Compile Include="Rooms\Config\EssentialsHuddleVtc1PropertiesConfig.cs" />
<Compile Include="Rooms\Config\EssentialsNDisplayRoomPropertiesConfig.cs" />
<Compile Include="Rooms\Config\EssentialsPresentationPropertiesConfig.cs" />
<Compile Include="Rooms\Config\EssentialsVolumeLevelConfig.cs" />
<Compile Include="Rooms\Emergency\EsentialsRoomEmergencyContactClosure.cs" />
<Compile Include="Rooms\EssentialsRoomBase.cs" />
<Compile Include="Rooms\Config\EssentialsRoomConfig.cs" />
<Compile Include="Rooms\Config\EssentialsRoomEmergencyConfig.cs" />
<Compile Include="Rooms\Interfaces.cs" />
<Compile Include="Rooms\iOccupancyStatusProvider.cs" />
<Compile Include="Rooms\Types\EssentialsDualDisplayRoom.cs" />
<Compile Include="Rooms\Types\EssentialsHuddleSpaceRoom.cs" />
<Compile Include="Rooms\Types\EssentialsHuddleVtc1Room.cs" />
<Compile Include="Rooms\Types\EssentialsNDisplayRoomBase.cs" />
<Compile Include="Room\Behaviours\RoomOnToDefaultSourceWhenOccupied.cs" />
<Compile Include="Room\EssentialsRoomBase.cs" />
<Compile Include="Room\Interfaces.cs" />
<Compile Include="Room\iOccupancyStatusProvider.cs" />
<Compile Include="Routing\DummyRoutingInputsDevice.cs" />
<Compile Include="Routing\ICardPortsDevice.cs" />
<Compile Include="InUseTracking\IInUseTracking.cs" />
@@ -297,10 +271,10 @@
<Compile Include="Monitoring\StatusMonitorBase.cs" />
<Compile Include="Monitoring\Interfaces.cs" />
<Compile Include="Monitoring\GenericCommunicationMonitor.cs" />
<Compile Include="Devices\Interfaces\AudioInterfaces.cs" />
<Compile Include="Devices\Interfaces\IAttachVideoStatusExtensions.cs" />
<Compile Include="Devices\Interfaces\IHasFeedbacks.cs" />
<Compile Include="Devices\Base Classes\SmartObjectBaseTypes.cs" />
<Compile Include="Devices\AudioInterfaces.cs" />
<Compile Include="Devices\IAttachVideoStatusExtensions.cs" />
<Compile Include="Devices\IHasFeedbacks.cs" />
<Compile Include="Devices\SmartObjectBaseTypes.cs" />
<Compile Include="Devices\PresentationDeviceType.cs" />
<Compile Include="Display\MockDisplay.cs" />
<Compile Include="Ethernet\EthernetStatistics.cs" />
@@ -344,11 +318,11 @@
<Compile Include="Devices\IrOutputPortController.cs" />
<Compile Include="Display\DisplayBase.cs" />
<Compile Include="Feedbacks\FeedbackBase.cs" />
<Compile Include="Rooms\Room.cs" />
<Compile Include="Room\Room.cs" />
<Compile Include="SmartObjects\SubpageReferencList\SourceListSubpageReferenceList.cs" />
<Compile Include="Touchpanels\ModalDialog.cs" />
<Compile Include="TriListBridges\HandlerBridge.cs" />
<Compile Include="Devices\Interfaces\Interfaces.cs" />
<Compile Include="Devices\FIND HOMES Interfaces.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SigHelper.cs" />
<Compile Include="SmartObjects\SubpageReferencList\SubpageReferenceList.cs" />

View File

@@ -21,30 +21,70 @@ namespace PepperDash.Essentials.Core
[Description("Wrapper class for all HR-Series remotes")]
public class Hrxx0WirelessRemoteController : EssentialsBridgeableDevice, IHasFeedback
{
private CenRfgwController _gateway;
private Hr1x0WirelessRemoteBase _remote;
public FeedbackCollection<Feedback> Feedbacks { get; set; }
public CrestronCollection<Button> Buttons { get { return _remote.Button; } }
private DeviceConfig _config;
public Hrxx0WirelessRemoteController(string key, Func<DeviceConfig, Hr1x0WirelessRemoteBase> preActivationFunc,
DeviceConfig config)
: base(key, config.Name)
{
Feedbacks = new FeedbackCollection<Feedback>();
AddPreActivationAction(() =>
var props = JsonConvert.DeserializeObject<CrestronRemotePropertiesConfig>(config.Properties.ToString());
var type = config.Type;
var rfId = (uint)props.Control.InfinetIdInt;
_config = config;
GatewayBase gateway;
if (props.GatewayDeviceKey == "processor")
{
_remote = preActivationFunc(config);
gateway = Global.ControlSystem.ControllerRFGatewayDevice;
}
_remote.ButtonStateChange += new ButtonEventHandler(_remote_ButtonStateChange);
else
{
var gatewayDev = DeviceManager.GetDeviceForKey(props.GatewayDeviceKey) as CenRfgwController;
if (gatewayDev == null)
{
Debug.Console(0, "GetHr1x0WirelessRemote: Device '{0}' is not a valid device", props.GatewayDeviceKey);
}
if (gatewayDev != null)
{
Debug.Console(0, "GetHr1x0WirelessRemote: Device '{0}' is a valid device", props.GatewayDeviceKey);
gateway = gatewayDev.GateWay;
_gateway = gatewayDev;
}
}
Feedbacks.Add(new BoolFeedback("BatteryCritical", () => _remote.BatteryCriticalFeedback.BoolValue));
Feedbacks.Add(new BoolFeedback("BatteryLow", () => _remote.BatteryLowFeedback.BoolValue));
Feedbacks.Add(new IntFeedback("BatteryVoltage", () => _remote.BatteryVoltageFeedback.UShortValue));
if (_gateway == null) return;
_remote.BaseEvent += new BaseEventHandler(_remote_BaseEvent);
});
_gateway.IsReadyEvent += _gateway_IsReadyEvent;
if (_gateway.IsReady)
{
AddPreActivationAction(() =>
{
_remote = preActivationFunc(config);
RegisterEvents();
});
}
}
void _gateway_IsReadyEvent(object sender, PepperDash_Essentials_Core.IsReadyEventArgs e)
{
if (e.IsReady != true) return;
_remote = GetHr1x0WirelessRemote(_config);
RegisterEvents();
}
void _remote_BaseEvent(GenericBase device, BaseEventArgs args)
@@ -57,6 +97,17 @@ namespace PepperDash.Essentials.Core
Feedbacks["BatteryVoltage"].FireUpdate();
}
private void RegisterEvents()
{
_remote.ButtonStateChange += _remote_ButtonStateChange;
Feedbacks.Add(new BoolFeedback("BatteryCritical", () => _remote.BatteryCriticalFeedback.BoolValue));
Feedbacks.Add(new BoolFeedback("BatteryLow", () => _remote.BatteryLowFeedback.BoolValue));
Feedbacks.Add(new IntFeedback("BatteryVoltage", () => _remote.BatteryVoltageFeedback.UShortValue));
_remote.BaseEvent += _remote_BaseEvent;
}
void _remote_ButtonStateChange(GenericBase device, ButtonEventArgs args)
{
try
@@ -112,22 +163,29 @@ namespace PepperDash.Essentials.Core
return null;
}
Hr1x0WirelessRemoteBase remoteBase;
switch (type)
{
case ("hr100"):
return new Hr100(rfId, gateway);
remoteBase = new Hr100(rfId, gateway);
break;
case ("hr150"):
return new Hr150(rfId, gateway);
remoteBase = new Hr150(rfId, gateway);
break;
case ("hr310"):
return new Hr310(rfId, gateway);
remoteBase = new Hr310(rfId, gateway);
break;
default:
return null;
}
}
static void gateway_BaseEvent(GenericBase device, BaseEventArgs args)
{
throw new NotImplementedException();
// register the device when using an internal RF gateway
if (props.GatewayDeviceKey == "processor")
{
remoteBase.RegisterWithLogging(config.Key);
}
return remoteBase;
}
#endregion
@@ -249,4 +307,4 @@ namespace PepperDash.Essentials.Core
trilist.BooleanInput[join].BoolValue = b;
}
}
}
}

View File

@@ -1,12 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.Scheduler;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Devices;
namespace PepperDash.Essentials.Core.Rooms
namespace PepperDash.Essentials.Core
{
/// <summary>
/// A device that when linked to a room can power the room on when enabled during scheduled hours.

View File

@@ -0,0 +1,315 @@
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;
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>
/// The config name of the source list
/// </summary>
public string SourceListKey { get; set; }
/// <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 LogoUrl { 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();
});
}
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

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core.Rooms
namespace PepperDash.Essentials.Core
{
/// <summary>
/// For rooms with in call feedback

View File

@@ -1,26 +0,0 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.Rooms.Config
{
public class DDVC01RoomPropertiesConfig : EssentialsHuddleVtc1PropertiesConfig
{
[JsonProperty("roomPhoneNumber")]
public string RoomPhoneNumber { get; set; }
[JsonProperty("roomURI")]
public string RoomURI { get; set; }
[JsonProperty("speedDials")]
public List<DDVC01SpeedDial> SpeedDials { get; set; }
[JsonProperty("volumeSliderNames")]
public List<string> VolumeSliderNames { get; set; }
}
public class DDVC01SpeedDial
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("number")]
public string Number { get; set; }
}
}

View File

@@ -1,9 +0,0 @@
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.Rooms.Config
{
public class EssentialsDualDisplayRoomPropertiesConfig : EssentialsNDisplayRoomPropertiesConfig
{
}
}

View File

@@ -1,35 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.Rooms.Config
{
/// <summary>
///
/// </summary>
public class EssentialsHuddleRoomPropertiesConfig : EssentialsRoomPropertiesConfig
{
/// <summary>
/// The key of the default display device
/// </summary>
[JsonProperty("defaultDisplayKey")]
public string DefaultDisplayKey { get; set; }
/// <summary>
/// The key of the default audio device
/// </summary>
[JsonProperty("defaultAudioKey")]
public string DefaultAudioKey { get; set; }
/// <summary>
/// The key of the source list for the room
/// </summary>
[JsonProperty("sourceListKey")]
public string SourceListKey { get; set; }
/// <summary>
/// The key of the default source item from the source list
/// </summary>
[JsonProperty("defaultSourceItem")]
public string DefaultSourceItem { get; set; }
}
}

View File

@@ -1,12 +0,0 @@
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core.Rooms.Config
{
public class EssentialsHuddleVtc1PropertiesConfig : EssentialsHuddleRoomPropertiesConfig
{
[JsonProperty("videoCodecKey")]
public string VideoCodecKey { get; set; }
[JsonProperty("audioCodecKey")]
public string AudioCodecKey { get; set; }
}
}

View File

@@ -1,28 +0,0 @@
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using Newtonsoft.Json;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.Rooms.Config
{
/// <summary>
///
/// </summary>
public class EssentialsNDisplayRoomPropertiesConfig : EssentialsHuddleRoomPropertiesConfig
{
[JsonProperty("defaultAudioBehavior")]
public string DefaultAudioBehavior { get; set; }
[JsonProperty("defaultVideoBehavior")]
public string DefaultVideoBehavior { get; set; }
[JsonProperty("destinationListKey")]
public string DestinationListKey { get; set; }
}
public class DisplayItem : IKeyName
{
public string Key { get; set; }
public string Name { get; set; }
}
}

View File

@@ -1,23 +0,0 @@
using System.Collections.Generic;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.Rooms.Config
{
/// <summary>
///
/// </summary>
public class EssentialsPresentationRoomPropertiesConfig : EssentialsRoomPropertiesConfig
{
public string DefaultAudioBehavior { get; set; }
public string DefaultAudioKey { get; set; }
public string DefaultVideoBehavior { get; set; }
public List<string> DisplayKeys { get; set; }
public string SourceListKey { get; set; }
public bool HasDsp { get; set; }
public EssentialsPresentationRoomPropertiesConfig()
{
DisplayKeys = new List<string>();
}
}
}

View File

@@ -1,296 +0,0 @@
using System.Collections.Generic;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Privacy;
namespace PepperDash.Essentials.Core.Rooms.Config
{
public class EssentialsRoomConfigHelper
{
/// <summary>
/// Returns a room object from this config data
/// </summary>
/// <returns></returns>
public static Device GetRoomObject(DeviceConfig roomConfig)
{
var typeName = roomConfig.Type.ToLower();
EssentialsRoomBase rm;
if (typeName == "huddle")
{
var huddle = new EssentialsHuddleSpaceRoom(roomConfig);
return huddle;
}
if (typeName == "huddlevtc1")
{
rm = new EssentialsHuddleVtc1Room(roomConfig);
return rm;
}
if (typeName == "ddvc01Bridge")
{
return new Device(roomConfig.Key, roomConfig.Name); // placeholder device that does nothing.
}
if (typeName != "dualdisplay")
{
return null;
}
//rm = new EssentialsDualDisplayRoom();
return null;
}
/// <summary>
/// Gets and operating, standalone emergegncy object that can be plugged into a room.
/// Returns null if there is no emergency defined
/// </summary>
public static EssentialsRoomEmergencyBase GetEmergency(EssentialsRoomPropertiesConfig props, EssentialsRoomBase room)
{
// This emergency
var emergency = props.Emergency;
if (emergency == null)
{
return null;
}
//switch on emergency type here. Right now only contact and shutdown
var e = new EssentialsRoomEmergencyContactClosure(room.Key + "-emergency", props.Emergency, room);
DeviceManager.AddDevice(e);
return null;
}
/// <summary>
///
/// </summary>
/// <param name="props"></param>
/// <param name="room"></param>
/// <returns></returns>
public static MicrophonePrivacyController GetMicrophonePrivacy(
EssentialsRoomPropertiesConfig props, IPrivacy room)
{
var microphonePrivacy = props.MicrophonePrivacy;
if (microphonePrivacy == null)
{
Debug.Console(0, "Cannot create microphone privacy with null properties");
return null;
}
// Get the MicrophonePrivacy device from the device manager
var mP = (DeviceManager.GetDeviceForKey(props.MicrophonePrivacy.DeviceKey) as
MicrophonePrivacyController);
// Set this room as the IPrivacy device
if (mP == null)
{
Debug.Console(0, "ERROR: Selected device {0} is not MicrophonePrivacyController", props.MicrophonePrivacy.DeviceKey);
return null;
}
mP.SetPrivacyDevice(room);
var behaviour = props.MicrophonePrivacy.Behaviour.ToLower();
if (behaviour == null)
{
Debug.Console(0, "WARNING: No behaviour defined for MicrophonePrivacyController");
return null;
}
switch (behaviour)
{
case "trackroomstate":
{
// Tie LED enable to room power state
var essRoom = room as EssentialsRoomBase;
if (essRoom != null)
{
essRoom.OnFeedback.OutputChange += (o, a) =>
{
mP.EnableLeds = essRoom.OnFeedback.BoolValue;
};
mP.EnableLeds = essRoom.OnFeedback.BoolValue;
}
}
break;
case "trackcallstate":
{
// Tie LED enable to room power state
var inCallRoom = room as IHasInCallFeedback;
if (inCallRoom != null)
{
inCallRoom.InCallFeedback.OutputChange += (o, a) =>
{
mP.EnableLeds = inCallRoom.InCallFeedback.BoolValue;
};
mP.EnableLeds = inCallRoom.InCallFeedback.BoolValue;
}
}
break;
}
return mP;
}
}
/// <summary>
///
/// </summary>
public class EssentialsRoomPropertiesConfig
{
[JsonProperty("addresses")]
public EssentialsRoomAddressPropertiesConfig Addresses { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("emergency")]
public EssentialsRoomEmergencyConfig Emergency { get; set; }
[JsonProperty("help")]
public EssentialsHelpPropertiesConfig Help { get; set; }
[JsonProperty("helpMessage")]
public string HelpMessage { get; set; }
[JsonProperty("environment")]
public EssentialsEnvironmentPropertiesConfig Environment { get; set; }
[JsonProperty("logo")]
public EssentialsLogoPropertiesConfig Logo { get; set; }
[JsonProperty("microphonePrivacy")]
public EssentialsRoomMicrophonePrivacyConfig MicrophonePrivacy { get; set; }
[JsonProperty("occupancy")]
public EssentialsRoomOccSensorConfig Occupancy { get; set; }
[JsonProperty("oneButtonMeeting")]
public EssentialsOneButtonMeetingPropertiesConfig OneButtonMeeting { get; set; }
[JsonProperty("shutdownVacancySeconds")]
public int ShutdownVacancySeconds { get; set; }
[JsonProperty("shutdownPromptSeconds")]
public int ShutdownPromptSeconds { get; set; }
[JsonProperty("tech")]
public EssentialsRoomTechConfig Tech { get; set; }
[JsonProperty("volumes")]
public EssentialsRoomVolumesConfig Volumes { get; set; }
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
}
public class EssentialsEnvironmentPropertiesConfig
{
public bool Enabled { get; set; }
[JsonProperty("deviceKeys")]
public List<string> DeviceKeys { get; set; }
public EssentialsEnvironmentPropertiesConfig()
{
DeviceKeys = new List<string>();
}
}
public class EssentialsRoomMicrophonePrivacyConfig
{
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
[JsonProperty("behaviour")]
public string Behaviour { get; set; }
}
/// <summary>
/// Properties for the help text box
/// </summary>
public class EssentialsHelpPropertiesConfig
{
[JsonProperty("message")]
public string Message { get; set; }
[JsonProperty("showCallButton")]
public bool ShowCallButton { get; set; }
/// <summary>
/// Defaults to "Call Help Desk"
/// </summary>
[JsonProperty("callButtonText")]
public string CallButtonText { get; set; }
public EssentialsHelpPropertiesConfig()
{
CallButtonText = "Call Help Desk";
}
}
/// <summary>
///
/// </summary>
public class EssentialsOneButtonMeetingPropertiesConfig
{
[JsonProperty("enable")]
public bool Enable { get; set; }
}
public class EssentialsRoomAddressPropertiesConfig
{
[JsonProperty("phoneNumber")]
public string PhoneNumber { get; set; }
[JsonProperty("sipAddress")]
public string SipAddress { get; set; }
}
/// <summary>
/// Properties for the room's logo on panels
/// </summary>
public class EssentialsLogoPropertiesConfig
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("url")]
public string Url { get; set; }
/// <summary>
/// Gets either the custom URL, a local-to-processor URL, or null if it's a default logo
/// </summary>
public string GetUrl()
{
if (Type == "url")
return Url;
if (Type == "system")
return string.Format("http://{0}:8080/logo.png",
CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0));
return null;
}
}
/// <summary>
/// Represents occupancy sensor(s) setup for a room
/// </summary>
public class EssentialsRoomOccSensorConfig
{
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
[JsonProperty("timeoutMinutes")]
public int TimeoutMinutes { get; set; }
}
public class EssentialsRoomTechConfig
{
[JsonProperty("password")]
public string Password { get; set; }
}
}

View File

@@ -1,30 +0,0 @@
namespace PepperDash.Essentials.Core.Rooms.Config
{
/// <summary>
///
/// </summary>
public class EssentialsRoomEmergencyConfig
{
public EssentialsRoomEmergencyTriggerConfig Trigger { get; set; }
public string Behavior { get; set; }
}
/// <summary>
///
/// </summary>
public class EssentialsRoomEmergencyTriggerConfig
{
/// <summary>
/// contact,
/// </summary>
public string Type { get; set; }
/// <summary>
/// Input number if contact
/// </summary>
public int Number { get; set; }
public bool TriggerOnClose { get; set; }
}
}

View File

@@ -1,64 +0,0 @@
namespace PepperDash.Essentials
{
/// <summary>
///
/// </summary>
public class EssentialsRoomVolumesConfig
{
public EssentialsVolumeLevelConfig Master { get; set; }
public EssentialsVolumeLevelConfig Program { get; set; }
public EssentialsVolumeLevelConfig AudioCallRx { get; set; }
public EssentialsVolumeLevelConfig AudioCallTx { get; set; }
}
/// <summary>
///
/// </summary>
public class EssentialsVolumeLevelConfig
{
public string DeviceKey { get; set; }
public string Label { get; set; }
public int Level { get; set; }
/*
/// <summary>
/// Helper to get the device associated with key - one timer.
/// </summary>
public IBasicVolumeWithFeedback GetDevice()
{
// DM output card format: deviceKey--output~number, dm8x8-1--output~4
var match = Regex.Match(DeviceKey, @"([-_\w]+)--(\w+)~(\d+)");
if (match.Success)
{
var devKey = match.Groups[1].Value;
var chassis = DeviceManager.GetDeviceForKey(devKey) as DmChassisController;
if (chassis != null)
{
var outputNum = Convert.ToUInt32(match.Groups[3].Value);
if (chassis.VolumeControls.ContainsKey(outputNum)) // should always...
return chassis.VolumeControls[outputNum];
}
// No volume for some reason. We have failed as developers
return null;
}
// DSP format: deviceKey--levelName, biampTesira-1--master
match = Regex.Match(DeviceKey, @"([-_\w]+)--(.+)");
if (match.Success)
{
var devKey = match.Groups[1].Value;
var dsp = DeviceManager.GetDeviceForKey(devKey) as BiampTesiraForteDsp;
if (dsp != null)
{
var levelTag = match.Groups[2].Value;
if (dsp.LevelControlPoints.ContainsKey(levelTag)) // should always...
return dsp.LevelControlPoints[levelTag];
}
// No volume for some reason. We have failed as developers
return null;
}
return null;
}*/
}
}

View File

@@ -1,47 +0,0 @@
using System;
using Crestron.SimplSharpPro;
using PepperDash.Essentials.Core.Rooms.Config;
namespace PepperDash.Essentials.Core.Rooms
{
public class EssentialsRoomEmergencyContactClosure : EssentialsRoomEmergencyBase
{
EssentialsRoomBase Room;
string Behavior;
bool TriggerOnClose;
public EssentialsRoomEmergencyContactClosure(string key, EssentialsRoomEmergencyConfig config, EssentialsRoomBase room) :
base(key)
{
Room = room;
var cs = Global.ControlSystem;
if (config.Trigger.Type.Equals("contact", StringComparison.OrdinalIgnoreCase))
{
var portNum = (uint)config.Trigger.Number;
if (portNum <= cs.NumberOfDigitalInputPorts)
{
cs.DigitalInputPorts[portNum].Register();
cs.DigitalInputPorts[portNum].StateChange += EsentialsRoomEmergencyContactClosure_StateChange;
}
}
Behavior = config.Behavior;
TriggerOnClose = config.Trigger.TriggerOnClose;
}
void EsentialsRoomEmergencyContactClosure_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args)
{
if (args.State && TriggerOnClose || !args.State && !TriggerOnClose)
RunEmergencyBehavior();
}
/// <summary>
///
/// </summary>
public void RunEmergencyBehavior()
{
if (Behavior.Equals("shutdown"))
Room.Shutdown();
}
}
}

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