Compare commits

..

50 Commits

Author SHA1 Message Date
jdevito
f1590aeec8 fix: added 'CancelPasswordPrompt' join, updated linkToZoomApi 2022-09-06 14:10:21 -05:00
jdevito
f1d1ce9722 fix: added OnPasswordRequired event call in SubmitPassword method to clear popup when bridged 2022-09-06 14:04:19 -05:00
Andrew Welker
f5a352cf08 Merge pull request #990 from PepperDash/hotfix/essentials-cooling-routing
Magic Routing holds last requested route until cooling is complete
2022-09-02 11:37:46 -06:00
Neil Dorin
c4a23e0887 feat(essentials): Adds RoomUiBehaviorConfig for disabling activity buttons 2022-09-02 11:19:18 -06:00
Andrew Welker
7fe2d04d31 fix: add removal of RouteRequest when calling ReleaseRoute 2022-09-01 12:29:19 -06:00
Andrew Welker
358f44cfe5 refactor: remove completed request from dictionary 2022-09-01 11:57:40 -06:00
Andrew Welker
d7cccc0709 feat: add cooldown logic to Magic Routing
In some cases, a route can be requested while a sink is cooling down.
In those cases, the routing logic should keep track of requests for a
destination and wait until cooling is complete to request the new
route.
2022-09-01 11:47:52 -06:00
Andrew Welker
81b1117310 Merge pull request #988 from PepperDash/feature/cen-io-ir-104
Add Support for CEN-IO devices
2022-08-31 14:47:58 -06:00
jdevito
fb689c4484 fix: updated CEN-IO classes inheriting from EssentialsDevice to CrestronGenericBaseDevice to resolve activation issues 2022-08-31 14:43:58 -05:00
jdevito
40cb1b0fcf Merge remote-tracking branch 'origin/hotfix/huddle-room-interfaces' into feature/cen-io-ir-104 2022-08-31 11:55:15 -05:00
Jason DeVito
4574941288 fix: updated debug statement for DinCenCnController class referencing building a temp sensor device 2022-08-30 22:11:33 -05:00
Jason DeVito
122abc56e5 fix: added null checks in BuildDevice with debug statements if null 2022-08-30 22:02:47 -05:00
Jason DeVito
074ee190ad feat: added cen-io-ir-104 device and factory 2022-08-30 21:53:41 -05:00
Andrew Welker
68a0157fbe fix: add missing interface 2022-08-30 13:57:53 -06:00
Andrew Welker
e5393deea8 Merge pull request #980 from PepperDash/hotfix/zoomroom-bridge-updates
Hotfix/zoomroom bridge updates
2022-08-10 16:28:16 -06:00
Jason DeVito
c446c3a976 fix: updates to resolve directory display issues on touch panel when bridged 2022-08-10 17:12:30 -05:00
Jason DeVito
49e44ec850 fix: updated VideoCodecBase UpdateDirectoryXSig to handle directory results that are greater than 1023, XSig maximimum index 2022-08-10 15:49:41 -05:00
Andrew Welker
0ec42f8de2 Merge pull request #976 from PepperDash/hotfix/fix-lightingScene-scene-select-index
Lighting and Display Base updates to support extending joinMaps
2022-08-08 13:29:01 -06:00
Jason DeVito
008c82edb9 fix: updated lighting and display base; fix: lightingBase scene recall link to api index out of range exception 2022-08-08 13:54:17 -05:00
Neil Dorin
3033322212 Merge pull request #973 from PepperDash/hotfix/multiple-display-routing-support
Fix interface type check for routing
2022-08-01 12:34:16 -06:00
Neil Dorin
5b350c7a0c Updates interface type for other condition 2022-08-01 12:19:43 -06:00
Neil Dorin
afd2198eef Uses a less specific interface type for routing 2022-08-01 12:19:28 -06:00
Neil Dorin
05dadbe8ee Merge pull request #963 from PepperDash/hotfix/typo-in-RoutingPort-constructor
Hotfix/typo in routing port constructor
2022-06-22 09:54:43 -06:00
Neil Dorin
c39fd231bf Merge pull request #914 from Willis1776/bugfix/routingPort-typo-isInternal-Constructor
Typo in RoutingPort Constructor - isInternal
2022-06-22 09:38:30 -06:00
Neil Dorin
0df587071d Merge branch 'main' into bugfix/routingPort-typo-isInternal-Constructor 2022-06-22 09:14:31 -06:00
Neil Dorin
cd4f2d5edd Merge pull request #952 from PepperDash/hotfix/c2nio-factory-reference-update
fix: corrects issue #951, c2nio incorrect factory reference
2022-06-08 14:29:43 -06:00
Jason DeVito
59b18d713b fix: corrects issue #951, c2nio incorrect factory reference 2022-06-08 15:12:32 -05:00
Neil Dorin
a7db15d9fd Merge pull request #943 from PepperDash/hotfix/zoom-recording-prompt
Hotfix/zoom recording prompt
2022-05-18 17:14:19 -06:00
Neil Dorin
b8442e7048 feat(essentials): Format update for command 2022-05-18 16:33:21 -06:00
Neil Dorin
1e65c961c6 feat(essentials): Adds new interface capabilities
* ability to admit a participant from waiting room
* ability to acknowledge a meeting recording consent prompt
2022-05-17 15:36:00 -06:00
Neil Dorin
bdc4f0ae28 fix(essentials): updates recording property name 2022-05-17 13:20:53 -06:00
Neil Dorin
82ac34d3b6 fix(essentials): Updates Status.Call subscription mechanism to persist properly
Makes sure all subscriptions are un and resubscribed whenever Status.Call is constructed
2022-05-17 11:26:19 -06:00
Neil Dorin
23555e5174 Merge branch 'main' into hotfix/zoom-osd-device 2022-05-16 14:20:38 -06:00
Neil Dorin
7c892b4f71 Merge pull request #936 from PepperDash/hotfix/zoomroom-duplicate-passwordRequired-eventhandlers
fix: removed duplicate PasswordRequired event handler from LinkZoomRo…
2022-04-26 14:50:40 -06:00
Jason DeVito
1abe54fa48 fix: removed duplicate PasswordRequired event handler from LinkZoomRoomToApi method 2022-04-26 15:32:34 -05:00
Jason DeVito
309605ee38 fix: updated packages.config to reference PepperDash Core 1.1.1, previously referencing RC build 2022-03-29 16:04:14 -05:00
Jason DeVito
e2b8e356ff fix: Updated ZoomRoom constructor to build HdmiOutput1,2,3 2022-03-29 16:03:46 -05:00
Jason DeVito
832102f4bb feat: updated ExecuteSwitch to turn the display power on if _PowerIsOn is false 2022-03-29 16:02:59 -05:00
Neil Dorin
b23b7cb813 fix(essentials): #927 moves SetUpRouting() to constructor 2022-03-29 12:49:49 -06:00
Andrew Welker
b42d487c4c Merge pull request #918 from PepperDash/release/1.10.0
Release/1.10.0
2022-03-16 08:05:25 -06:00
Michael Willis
5f668c7173 Typo in RoutingPort Constructor - isInternal 2022-03-08 09:42:53 -07:00
Andrew Welker
6db5a9b2ca Merge pull request #913 from PepperDash/feature/cleanup-debug-statements
Feature/cleanup debug statements
2022-03-03 15:14:34 -07:00
Neil Dorin
89dd098ea6 feat(essentials): #912 Updates to GenericCommunicationMonitor to better monitor socket status 2022-03-03 14:39:54 -07:00
Neil Dorin
787c8eb954 feat(essentials): Adds new interface and event to notify if video unmute is requested 2022-03-01 21:43:38 -07:00
Neil Dorin
97b9ed5016 fix(essentials): Fixes SetupCameras to not add duplicate cameras to the list 2022-02-28 19:21:27 -07:00
Neil Dorin
06fdee313a fix(essentials): adds missing property decorators and unmutes video on camera select 2022-02-25 21:10:44 -07:00
Neil Dorin
b3f7568469 fix(essentials): updates to IHasDirectory and ZoomRoom
Prevents serialization of CurrentDirectoryResults object.
Modified OnDirectoryResultsReturne helper method for ZoomRoom to fix stripping of contacts
2022-02-24 22:03:03 -07:00
Neil Dorin
55ab593d73 feat(essentails): #911 swaps cisco comm monitor poll string 2022-02-24 14:34:38 -07:00
Neil Dorin
a06652ee61 chore(essentials): Cleans up some debug statements no longer needed 2022-02-21 12:06:09 -07:00
Neil Dorin
2502947df8 Merge pull request #899 from PepperDash/hotfix/queue-thread-name
Add name to `GenericQueue` Thread
2022-02-02 10:16:38 -07:00
33 changed files with 4049 additions and 3484 deletions

View File

@@ -202,6 +202,9 @@ namespace PepperDash.Essentials.Room.Config
[JsonProperty("fusion")] [JsonProperty("fusion")]
public EssentialsRoomFusionConfig Fusion { get; set; } public EssentialsRoomFusionConfig Fusion { get; set; }
[JsonProperty("essentialsRoomUiBehaviorConfig", NullValueHandling=NullValueHandling.Ignore)]
public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; }
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")] [JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; } public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
@@ -218,6 +221,12 @@ namespace PepperDash.Essentials.Room.Config
} }
} }
public class EssentialsRoomUiBehaviorConfig
{
[JsonProperty("disableActivityButtonsWhileWarmingCooling")]
public bool DisableActivityButtonsWhileWarmingCooling { get; set; }
}
public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig
{ {
[JsonProperty("defaultAudioKey")] [JsonProperty("defaultAudioKey")]

View File

@@ -708,11 +708,12 @@ namespace PepperDash.Essentials
IRoutingSink dest = null; IRoutingSink dest = null;
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase)) if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
dest = DefaultAudioDevice as IRoutingSinkNoSwitching; dest = DefaultAudioDevice as IRoutingSink;
else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
dest = DefaultDisplay; dest = DefaultDisplay;
else else
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching; dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink;
if (dest == null) if (dest == null)
{ {

View File

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

View File

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

View File

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

View File

@@ -51,7 +51,7 @@ namespace PepperDash.Essentials
public override void Show() public override void Show()
{ {
Debug.Console(2, "Showing ScreenSaverController: {0:X2}", TriList.ID); //Debug.Console(2, "Showing ScreenSaverController: {0:X2}", TriList.ID);
if (_parent.AvDriver != null) if (_parent.AvDriver != null)
{ {
@@ -67,11 +67,11 @@ namespace PepperDash.Essentials
public override void Hide() public override void Hide()
{ {
Debug.Console(2, "Hiding ScreenSaverController: {0:X2}", TriList.ID); //Debug.Console(2, "Hiding ScreenSaverController: {0:X2}", TriList.ID);
if (PositionTimer != null) if (PositionTimer != null)
{ {
Debug.Console(2, "Stopping PositionTimer: {0:X2}", TriList.ID); //Debug.Console(2, "Stopping PositionTimer: {0:X2}", TriList.ID);
PositionTimer.Stop(); PositionTimer.Stop();
PositionTimer.Dispose(); PositionTimer.Dispose();
PositionTimer = null; PositionTimer = null;
@@ -89,7 +89,7 @@ namespace PepperDash.Essentials
void StartPositionTimer() void StartPositionTimer()
{ {
Debug.Console(2, "Starting Position Timer: {0:X2}", TriList.ID); //Debug.Console(2, "Starting Position Timer: {0:X2}", TriList.ID);
if (PositionTimer == null) if (PositionTimer == null)
{ {
@@ -122,7 +122,7 @@ namespace PepperDash.Essentials
CurrentPositionIndex = 0; CurrentPositionIndex = 0;
} }
Debug.Console(2, "ScreenSaver Position Timer Expired: Setting new position: {0} ID: {1:X2}", CurrentPositionIndex, TriList.ID); //Debug.Console(2, "ScreenSaver Position Timer Expired: Setting new position: {0} ID: {1:X2}", CurrentPositionIndex, TriList.ID);
} }
// //
@@ -134,7 +134,7 @@ namespace PepperDash.Essentials
void ClearAllPositions() void ClearAllPositions()
{ {
Debug.Console(2, "Hiding all screensaver positions: {0:X2}", TriList.ID); //Debug.Console(2, "Hiding all screensaver positions: {0:X2}", TriList.ID);
PositionInterlock.HideAndClear(); PositionInterlock.HideAndClear();
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -105,9 +105,6 @@ namespace PepperDash.Essentials.Core
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey, protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey,
EiscApiAdvanced bridge) EiscApiAdvanced bridge)
{ {
var inputNumber = 0;
var inputKeys = new List<string>();
var joinMap = new DisplayControllerJoinMap(joinStart); var joinMap = new DisplayControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
@@ -124,133 +121,141 @@ namespace PepperDash.Essentials.Core
Debug.Console(0,this,"Please update config to use 'eiscapiadvanced' to get all join map features for this device."); Debug.Console(0,this,"Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
} }
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); LinkDisplayToApi(displayDevice, trilist, joinMap);
Debug.Console(0, "Linking to Display: {0}", displayDevice.Name);
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = displayDevice.Name;
var commMonitor = displayDevice as ICommunicationMonitor;
if (commMonitor != null)
{
commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
}
var inputNumberFeedback = new IntFeedback(() => inputNumber);
// Two way feedbacks
var twoWayDisplay = displayDevice as TwoWayDisplayBase;
if (twoWayDisplay != null)
{
trilist.SetBool(joinMap.IsTwoWayDisplay.JoinNumber, true);
twoWayDisplay.CurrentInputFeedback.OutputChange += (o, a) => Debug.Console(0, "CurrentInputFeedback_OutputChange {0}", a.StringValue);
inputNumberFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputSelect.JoinNumber]);
}
// Power Off
trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () =>
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOff();
});
var twoWayDisplayDevice = displayDevice as TwoWayDisplayBase;
if (twoWayDisplayDevice != null)
{
twoWayDisplayDevice.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (!a.BoolValue)
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
}
else
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
}
};
twoWayDisplayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
twoWayDisplayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
}
// PowerOn
trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () =>
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOn();
});
for (int i = 0; i < displayDevice.InputPorts.Count; i++)
{
if (i < joinMap.InputNamesOffset.JoinSpan)
{
inputKeys.Add(displayDevice.InputPorts[i].Key);
var tempKey = inputKeys.ElementAt(i);
trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset.JoinNumber + i),
() => displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector));
Debug.Console(2, displayDevice, "Setting Input Select Action on Digital Join {0} to Input: {1}",
joinMap.InputSelectOffset.JoinNumber + i, displayDevice.InputPorts[tempKey].Key.ToString());
trilist.StringInput[(ushort)(joinMap.InputNamesOffset.JoinNumber + i)].StringValue = displayDevice.InputPorts[i].Key.ToString();
}
else
Debug.Console(0, displayDevice, Debug.ErrorLogLevel.Warning, "Device has {0} inputs. The Join Map allows up to {1} inputs. Discarding inputs {2} - {3} from bridge.",
displayDevice.InputPorts.Count, joinMap.InputNamesOffset.JoinSpan, i + 1, displayDevice.InputPorts.Count);
}
Debug.Console(2, displayDevice, "Setting Input Select Action on Analog Join {0}", joinMap.InputSelect);
trilist.SetUShortSigAction(joinMap.InputSelect.JoinNumber, (a) =>
{
if (a == 0)
{
displayDevice.PowerOff();
inputNumber = 0;
}
else if (a > 0 && a < displayDevice.InputPorts.Count && a != inputNumber)
{
displayDevice.ExecuteSwitch(displayDevice.InputPorts.ElementAt(a - 1).Selector);
inputNumber = a;
}
else if (a == 102)
{
displayDevice.PowerToggle();
}
if (twoWayDisplay != null)
inputNumberFeedback.FireUpdate();
});
var volumeDisplay = displayDevice as IBasicVolumeControls;
if (volumeDisplay == null) return;
trilist.SetBoolSigAction(joinMap.VolumeUp.JoinNumber, volumeDisplay.VolumeUp);
trilist.SetBoolSigAction(joinMap.VolumeDown.JoinNumber, volumeDisplay.VolumeDown);
trilist.SetSigTrueAction(joinMap.VolumeMute.JoinNumber, volumeDisplay.MuteToggle);
var volumeDisplayWithFeedback = volumeDisplay as IBasicVolumeWithFeedback;
if (volumeDisplayWithFeedback == null) return;
trilist.SetSigTrueAction(joinMap.VolumeMuteOn.JoinNumber, volumeDisplayWithFeedback.MuteOn);
trilist.SetSigTrueAction(joinMap.VolumeMuteOff.JoinNumber, volumeDisplayWithFeedback.MuteOff);
trilist.SetUShortSigAction(joinMap.VolumeLevel.JoinNumber, volumeDisplayWithFeedback.SetVolume);
volumeDisplayWithFeedback.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[joinMap.VolumeLevel.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMute.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMuteOn.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.VolumeMuteOff.JoinNumber]);
} }
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, DisplayControllerJoinMap joinMap)
{
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "Linking to Display: {0}", displayDevice.Name);
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = displayDevice.Name;
var commMonitor = displayDevice as ICommunicationMonitor;
if (commMonitor != null)
{
commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
}
var inputNumber = 0;
var inputKeys = new List<string>();
var inputNumberFeedback = new IntFeedback(() => inputNumber);
// Two way feedbacks
var twoWayDisplay = displayDevice as TwoWayDisplayBase;
if (twoWayDisplay != null)
{
trilist.SetBool(joinMap.IsTwoWayDisplay.JoinNumber, true);
twoWayDisplay.CurrentInputFeedback.OutputChange += (o, a) => Debug.Console(0, "CurrentInputFeedback_OutputChange {0}", a.StringValue);
inputNumberFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputSelect.JoinNumber]);
}
// Power Off
trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () =>
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOff();
});
var twoWayDisplayDevice = displayDevice as TwoWayDisplayBase;
if (twoWayDisplayDevice != null)
{
twoWayDisplayDevice.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (!a.BoolValue)
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
}
else
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
}
};
twoWayDisplayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
twoWayDisplayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
}
// PowerOn
trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () =>
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOn();
});
for (int i = 0; i < displayDevice.InputPorts.Count; i++)
{
if (i < joinMap.InputNamesOffset.JoinSpan)
{
inputKeys.Add(displayDevice.InputPorts[i].Key);
var tempKey = inputKeys.ElementAt(i);
trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset.JoinNumber + i),
() => displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector));
Debug.Console(2, displayDevice, "Setting Input Select Action on Digital Join {0} to Input: {1}",
joinMap.InputSelectOffset.JoinNumber + i, displayDevice.InputPorts[tempKey].Key.ToString());
trilist.StringInput[(ushort)(joinMap.InputNamesOffset.JoinNumber + i)].StringValue = displayDevice.InputPorts[i].Key.ToString();
}
else
Debug.Console(0, displayDevice, Debug.ErrorLogLevel.Warning, "Device has {0} inputs. The Join Map allows up to {1} inputs. Discarding inputs {2} - {3} from bridge.",
displayDevice.InputPorts.Count, joinMap.InputNamesOffset.JoinSpan, i + 1, displayDevice.InputPorts.Count);
}
Debug.Console(2, displayDevice, "Setting Input Select Action on Analog Join {0}", joinMap.InputSelect);
trilist.SetUShortSigAction(joinMap.InputSelect.JoinNumber, (a) =>
{
if (a == 0)
{
displayDevice.PowerOff();
inputNumber = 0;
}
else if (a > 0 && a < displayDevice.InputPorts.Count && a != inputNumber)
{
displayDevice.ExecuteSwitch(displayDevice.InputPorts.ElementAt(a - 1).Selector);
inputNumber = a;
}
else if (a == 102)
{
displayDevice.PowerToggle();
}
if (twoWayDisplay != null)
inputNumberFeedback.FireUpdate();
});
var volumeDisplay = displayDevice as IBasicVolumeControls;
if (volumeDisplay == null) return;
trilist.SetBoolSigAction(joinMap.VolumeUp.JoinNumber, volumeDisplay.VolumeUp);
trilist.SetBoolSigAction(joinMap.VolumeDown.JoinNumber, volumeDisplay.VolumeDown);
trilist.SetSigTrueAction(joinMap.VolumeMute.JoinNumber, volumeDisplay.MuteToggle);
var volumeDisplayWithFeedback = volumeDisplay as IBasicVolumeWithFeedback;
if (volumeDisplayWithFeedback == null) return;
trilist.SetSigTrueAction(joinMap.VolumeMuteOn.JoinNumber, volumeDisplayWithFeedback.MuteOn);
trilist.SetSigTrueAction(joinMap.VolumeMuteOff.JoinNumber, volumeDisplayWithFeedback.MuteOff);
trilist.SetUShortSigAction(joinMap.VolumeLevel.JoinNumber, volumeDisplayWithFeedback.SetVolume);
volumeDisplayWithFeedback.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[joinMap.VolumeLevel.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMute.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMuteOn.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.VolumeMuteOff.JoinNumber]);
}
} }
/// <summary> /// <summary>

View File

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

View File

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

View File

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

View File

@@ -183,6 +183,7 @@
<Compile Include="Crestron IO\Inputs\GenericVersiportInputDevice.cs" /> <Compile Include="Crestron IO\Inputs\GenericVersiportInputDevice.cs" />
<Compile Include="Crestron IO\Inputs\IDigitalInput.cs" /> <Compile Include="Crestron IO\Inputs\IDigitalInput.cs" />
<Compile Include="Crestron IO\IOPortConfig.cs" /> <Compile Include="Crestron IO\IOPortConfig.cs" />
<Compile Include="Crestron IO\Ir\CenIoIr104Controller.cs" />
<Compile Include="Crestron IO\Relay\CenIoRy104Controller.cs" /> <Compile Include="Crestron IO\Relay\CenIoRy104Controller.cs" />
<Compile Include="Crestron IO\Relay\GenericRelayDevice.cs" /> <Compile Include="Crestron IO\Relay\GenericRelayDevice.cs" />
<Compile Include="Crestron IO\Relay\ISwitchedOutput.cs" /> <Compile Include="Crestron IO\Relay\ISwitchedOutput.cs" />

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -359,7 +359,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
} }
else else
{ {
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, "xStatus SystemUnit Software Version\r\n"); var command = string.Format("xCommand Peripherals HeartBeat ID: {0}{1}", CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, Delimiter);
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, command);
} }
if (props.Sharing != null) if (props.Sharing != null)

View File

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

View File

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

View File

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

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Reflection;
using Crestron.SimplSharp.Ssh; using Crestron.SimplSharp.Ssh;
using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharp; using Crestron.SimplSharp;
@@ -1010,7 +1011,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, trilist.SetString(joinMap.DirectoryEntries.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length); Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length);
@@ -1025,7 +1026,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, trilist.SetString(joinMap.DirectoryEntries.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var directoryXSig = UpdateDirectoryXSig(args.Directory, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); var directoryXSig = UpdateDirectoryXSig(args.Directory, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length); Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length);
@@ -1036,10 +1037,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
{ {
if (!args.DeviceOnLine) return; if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, "\xFC"); trilist.SetString(joinMap.DirectoryEntries.JoinNumber, "\xFC");
UpdateDirectoryXSig(codec.CurrentDirectoryResult, UpdateDirectoryXSig(codec.CurrentDirectoryResult,
!codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
}; };
} }
@@ -1180,31 +1180,44 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot) private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot)
{ {
var contactIndex = 1; var xSigMaxIndex = 1023;
var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count]; var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count > xSigMaxIndex
? xSigMaxIndex
: directory.CurrentDirectoryResults.Count];
Debug.Console(2, this, "Is root {0} Directory Count: {1}", isRoot, directory.CurrentDirectoryResults.Count); Debug.Console(2, this, "IsRoot: {0}, Directory Count: {1}, TokenArray.Length: {2}", isRoot, directory.CurrentDirectoryResults.Count, tokenArray.Length);
foreach (var entry in directory.CurrentDirectoryResults) var contacts = directory.CurrentDirectoryResults.Count > xSigMaxIndex
? directory.CurrentDirectoryResults.Take(xSigMaxIndex)
: directory.CurrentDirectoryResults;
var contactsToDisplay = isRoot
? contacts.Where(c => c.ParentFolderId == "root")
: contacts.Where(c => c.ParentFolderId != "root");
var counterIndex = 1;
foreach (var entry in contactsToDisplay)
{ {
var arrayIndex = contactIndex - 1; var arrayIndex = counterIndex - 1;
var entryIndex = counterIndex;
Debug.Console(2, this, "Entry Name: {0}, Folder ID: {1}", entry.Name, entry.FolderId); Debug.Console(2, this, "Entry{2:0000} Name: {0}, Folder ID: {1}, Type: {3}, ParentFolderId: {4}",
entry.Name, entry.FolderId, entryIndex, entry.GetType().GetCType().FullName, entry.ParentFolderId);
if (entry is DirectoryFolder && entry.ParentFolderId == "root") if (entry is DirectoryFolder)
{ {
tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, String.Format("[+] {0}", entry.Name)); tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, String.Format("[+] {0}", entry.Name));
contactIndex++; counterIndex++;
continue; continue;
} }
tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, entry.Name); tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, entry.Name);
contactIndex++; counterIndex++;
} }
return GetXSigString(tokenArray); return GetXSigString(tokenArray);
} }

View File

@@ -31,10 +31,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
protected void NotifyPropertyChanged(string propertyName) protected void NotifyPropertyChanged(string propertyName)
{ {
if (PropertyChanged != null) var handler = PropertyChanged;
{ if (handler != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); {
} handler(this, new PropertyChangedEventArgs(propertyName));
}
else
{
Debug.Console(2, "PropertyChanged event is NULL");
}
} }
#endregion #endregion
@@ -778,13 +783,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
set set
{ {
//Debug.Console(2, "************************************setting value of meetingIsBeingRecorded to: {0}", value);
if (value != _meetingIsBeingRecorded) if (value != _meetingIsBeingRecorded)
{ {
_meetingIsBeingRecorded = value; _meetingIsBeingRecorded = value;
//Debug.Console(2, "********************************set value of meetingIsBeingRecorded to: {0}", _meetingIsBeingRecorded);
NotifyPropertyChanged("meetingIsBeingRecorded"); NotifyPropertyChanged("meetingIsBeingRecorded");
} }
} }
} }
public CallRecordInfo()
{
Debug.Console(2, Debug.ErrorLogLevel.Notice, "********************************************* CallRecordInfo() ******************************************");
}
} }
} }

View File

@@ -24,23 +24,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor,
IRouting, IRouting,
IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMuteWithUnmuteReqeust, IHasCameraAutoMode,
IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin,
IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting, IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting,
IHasMeetingLock, IHasMeetingRecording IHasMeetingLock, IHasMeetingRecordingWithPrompt
{ {
public event EventHandler VideoUnmuteRequested;
private const long MeetingRefreshTimer = 60000; private const long MeetingRefreshTimer = 60000;
public uint DefaultMeetingDurationMin { get; private set; } public uint DefaultMeetingDurationMin { get; private set; }
/// <summary> /// <summary>
/// CR LF /// CR LF CR LF Delimits an echoed response to a command
/// </summary> /// </summary>
private const string EchoDelimiter = "\x0D\x0A\x0D\x0A"; private const string EchoDelimiter = "\x0D\x0A\x0D\x0A";
private const string SendDelimiter = "\x0D"; private const string SendDelimiter = "\x0D";
/// <summary> /// <summary>
/// CR LF } CR LF /// CR LF } CR LF Delimits a JSON response
/// </summary> /// </summary>
private const string JsonDelimiter = "\x0D\x0A\x7D\x0D\x0A"; private const string JsonDelimiter = "\x0D\x0A\x7D\x0D\x0A";
@@ -111,14 +113,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this); eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this);
Output1 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, Output1 = new RoutingOutputPort(RoutingPortNames.HdmiOut1,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this); eRoutingPortConnectionType.Hdmi, null, this);
Output2 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, Output2 = new RoutingOutputPort(RoutingPortNames.HdmiOut2,
eRoutingSignalType.Video, eRoutingSignalType.Video,
eRoutingPortConnectionType.DisplayPort, null, this); eRoutingPortConnectionType.DisplayPort, null, this);
Output3 = new RoutingOutputPort(RoutingPortNames.HdmiOut3,
eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc); SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc);
CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc); CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc);
@@ -168,6 +174,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
MeetingIsLockedFeedback = new BoolFeedback(() => Configuration.Call.Lock.Enable ); MeetingIsLockedFeedback = new BoolFeedback(() => Configuration.Call.Lock.Enable );
MeetingIsRecordingFeedback = new BoolFeedback(() => Status.Call.CallRecordInfo.meetingIsBeingRecorded ); MeetingIsRecordingFeedback = new BoolFeedback(() => Status.Call.CallRecordInfo.meetingIsBeingRecorded );
RecordConsentPromptIsVisible = new BoolFeedback(() => _recordConsentPromptIsVisible);
SetUpRouting();
} }
public CommunicationGather PortGather { get; private set; } public CommunicationGather PortGather { get; private set; }
@@ -297,6 +307,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public RoutingInputPort CodecOsdIn { get; private set; } public RoutingInputPort CodecOsdIn { get; private set; }
public RoutingOutputPort Output1 { get; private set; } public RoutingOutputPort Output1 { get; private set; }
public RoutingOutputPort Output2 { get; private set; } public RoutingOutputPort Output2 { get; private set; }
public RoutingOutputPort Output3 { get; private set; }
#region ICommunicationMonitor Members #region ICommunicationMonitor Members
@@ -342,6 +353,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
Debug.Console(1, this, "Selected Camera with key: '{0}'", camera.Key); Debug.Console(1, this, "Selected Camera with key: '{0}'", camera.Key);
SelectedCamera = camera; SelectedCamera = camera;
if (CameraIsMutedFeedback.BoolValue)
{
CameraMuteOff();
}
} }
else else
{ {
@@ -400,10 +416,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
_currentDirectoryResult = value; _currentDirectoryResult = value;
Debug.Console(2, this, "CurrentDirectoryResult Updated. ResultsFolderId: {0}", Debug.Console(2, this, "CurrentDirectoryResult Updated. ResultsFolderId: {0} Contact Count: {1}",
_currentDirectoryResult.ResultsFolderId); _currentDirectoryResult.ResultsFolderId, _currentDirectoryResult.CurrentDirectoryResults.Count);
CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate();
OnDirectoryResultReturned(_currentDirectoryResult); OnDirectoryResultReturned(_currentDirectoryResult);
} }
@@ -484,25 +498,63 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private void SyncState_InitialSyncCompleted(object sender, EventArgs e) private void SyncState_InitialSyncCompleted(object sender, EventArgs e)
{ {
SetUpRouting();
SetIsReady(); SetIsReady();
} }
/// <summary>
/// Handles subscriptions to Status.Call and sub objects. Needs to be called whenever Status.Call is constructed
/// </summary>
private void SetUpCallFeedbackActions() private void SetUpCallFeedbackActions()
{ {
Status.Call.Sharing.PropertyChanged += HandleSharingStateUpdate; Status.Call.Sharing.PropertyChanged -= HandleSharingStateUpdate;
Status.Call.Sharing.PropertyChanged += HandleSharingStateUpdate;
Status.Call.PropertyChanged += (o, a) => Status.Call.PropertyChanged -= HandleCallStateUpdate;
{ Status.Call.PropertyChanged += HandleCallStateUpdate;
if (a.PropertyName == "Info")
{ Status.Call.CallRecordInfo.PropertyChanged -= HandleCallRecordInfoStateUpdate;
Debug.Console(1, this, "Updating Call Status"); Status.Call.CallRecordInfo.PropertyChanged += HandleCallRecordInfoStateUpdate;
UpdateCallStatus();
}
};
} }
private void HandleCallRecordInfoStateUpdate(object sender, PropertyChangedEventArgs a)
{
if (a.PropertyName == "meetingIsBeingRecorded")
{
MeetingIsRecordingFeedback.FireUpdate();
var meetingInfo = new MeetingInfo(MeetingInfo.Id,
MeetingInfo.Name,
MeetingInfo.Host,
MeetingInfo.Password,
GetSharingStatus(),
GetIsHostMyself(),
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = meetingInfo;
}
}
private void HandleCallStateUpdate(object sender, PropertyChangedEventArgs a)
{
switch (a.PropertyName)
{
case "Info":
{
Debug.Console(1, this, "Updating Call Status");
UpdateCallStatus();
break;
}
case "Status":
{
UpdateCallStatus();
break;
}
}
}
private void HandleSharingStateUpdate(object sender, PropertyChangedEventArgs a) private void HandleSharingStateUpdate(object sender, PropertyChangedEventArgs a)
{ {
if (a.PropertyName != "State") if (a.PropertyName != "State")
@@ -520,19 +572,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
var sharingStatus = GetSharingStatus(); var sharingStatus = GetSharingStatus();
MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue); MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
return; return;
} }
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host != null ? Participants.Host.Name : "None", var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host != null ? Participants.Host.Name : "None",
MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue); MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = meetingInfo; MeetingInfo = meetingInfo;
} }
catch (Exception e) catch (Exception e)
{ {
Debug.Console(1, this, "Error processing state property update. {0}", e.Message); Debug.Console(1, this, "Error processing state property update. {0}", e.Message);
Debug.Console(2, this, e.StackTrace); Debug.Console(2, this, e.StackTrace);
MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false, MeetingIsLockedFeedback.BoolValue); MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
} }
} }
@@ -541,6 +593,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// </summary> /// </summary>
private void SetUpFeedbackActions() private void SetUpFeedbackActions()
{ {
// Set these up initially.
SetUpCallFeedbackActions();
Configuration.Audio.Output.PropertyChanged += (o, a) => Configuration.Audio.Output.PropertyChanged += (o, a) =>
{ {
if (a.PropertyName == "Volume") if (a.PropertyName == "Volume")
@@ -635,7 +690,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
MeetingInfo.IsHost, MeetingInfo.IsHost,
MeetingInfo.IsSharingMeeting, MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost, MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue
); );
} }
}; };
@@ -668,41 +724,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
}; };
Status.Call.Sharing.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "State")
{
SharingContentIsOnFeedback.FireUpdate();
ReceivingContent.FireUpdate();
}
};
Status.Call.PropertyChanged += (o, a) =>
{
switch(a.PropertyName)
{
case "Info":
{
Debug.Console(1, this, "Updating Call Status");
UpdateCallStatus();
break;
}
case "Status":
{
UpdateCallStatus();
break;
}
}
};
Status.Call.CallRecordInfo.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "meetingIsBeingRecorded")
{
MeetingIsRecordingFeedback.FireUpdate();
}
};
Status.Sharing.PropertyChanged += (o, a) => Status.Sharing.PropertyChanged += (o, a) =>
{ {
@@ -734,7 +755,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
GetIsHostMyself(), GetIsHostMyself(),
MeetingInfo.IsSharingMeeting, MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost, MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue); MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = meetingInfo; MeetingInfo = meetingInfo;
break; break;
} }
@@ -1305,6 +1327,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
// This result will always be the complete contents of the directory and never // This result will always be the complete contents of the directory and never
// A subset of the results via a search // A subset of the results via a search
// Clear out any existing data
Status.Phonebook = new zStatus.Phonebook();
JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook);
var directoryResults = var directoryResults =
@@ -1318,10 +1343,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count);
} }
if (directoryResults.ResultsFolderId != "root") directoryResults.ResultsFolderId = "root";
{
directoryResults.ResultsFolderId = "root";
}
DirectoryRoot = directoryResults; DirectoryRoot = directoryResults;
@@ -1431,7 +1453,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
GetIsHostMyself(), GetIsHostMyself(),
MeetingInfo.IsSharingMeeting, MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost, MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue); MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = meetingInfo; MeetingInfo = meetingInfo;
PrintCurrentCallParticipants(); PrintCurrentCallParticipants();
@@ -1608,7 +1631,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
case "videounmuterequest": case "videounmuterequest":
{ {
// TODO: notify room of a request to unmute video var handler = VideoUnmuteRequested;
if (handler != null)
{
handler(this, null);
}
break; break;
} }
case "meetingneedspassword": case "meetingneedspassword":
@@ -1640,14 +1669,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (MeetingInfo == null) if (MeetingInfo == null)
{ {
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue); GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
UpdateCallStatus(); UpdateCallStatus();
break; break;
} }
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue); GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
UpdateCallStatus(); UpdateCallStatus();
@@ -1657,12 +1686,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (MeetingInfo == null) if (MeetingInfo == null)
{ {
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, false, MeetingIsLockedFeedback.BoolValue); GetSharingStatus(), false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
break; break;
} }
MeetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, MeetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password,
GetSharingStatus(), GetIsHostMyself(), false, false, MeetingIsLockedFeedback.BoolValue); GetSharingStatus(), GetIsHostMyself(), false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
break; break;
} }
@@ -1671,12 +1700,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
// TODO: notify user that host has disabled unmuting video // TODO: notify user that host has disabled unmuting video
break; break;
} }
case "updatedcallrecordinfo": case "updatecallrecordinfo":
{ {
JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.CallRecordInfo); JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.CallRecordInfo);
break; break;
} }
case "recordingconsent":
{
_recordConsentPromptIsVisible = responseObj["isShow"].Value<bool>();
RecordConsentPromptIsVisible.FireUpdate();
break;
}
case "phonecallstatus": case "phonecallstatus":
{ {
JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall); JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall);
@@ -1746,7 +1781,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (result.Success) if (result.Success)
{ {
MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue); MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
break; break;
} }
@@ -1841,6 +1876,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
case "video camera line": case "video camera line":
{ {
Status.Cameras.Clear();
JsonConvert.PopulateObject(responseObj.ToString(), Status.Cameras); JsonConvert.PopulateObject(responseObj.ToString(), Status.Cameras);
if (!_syncState.CamerasHaveBeenSetUp) if (!_syncState.CamerasHaveBeenSetUp)
@@ -1945,12 +1982,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
// If not crrently in a meeting, intialize the call object // If not crrently in a meeting, intialize the call object
if (callStatus != zStatus.eCallStatus.IN_MEETING && callStatus != zStatus.eCallStatus.CONNECTING_MEETING) if (callStatus != zStatus.eCallStatus.IN_MEETING && callStatus != zStatus.eCallStatus.CONNECTING_MEETING)
{ {
//Debug.Console(1, this, "[UpdateCallStatus] Creating new Status.Call object");
Status.Call = new zStatus.Call {Status = callStatus}; Status.Call = new zStatus.Call {Status = callStatus};
// Resubscribe to all property change events after Status.Call is reconstructed
SetUpCallFeedbackActions();
OnCallStatusChange(new CodecActiveCallItem() {Status = eCodecCallStatus.Disconnected}); OnCallStatusChange(new CodecActiveCallItem() {Status = eCodecCallStatus.Disconnected});
SetUpCallFeedbackActions();
} }
if (ActiveCalls.Count == 0) if (ActiveCalls.Count == 0)
@@ -2090,7 +2126,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
GetIsHostMyself(), GetIsHostMyself(),
!String.Equals(Status.Call.Info.meeting_type,"NORMAL"), !String.Equals(Status.Call.Info.meeting_type,"NORMAL"),
false, false,
MeetingIsLockedFeedback.BoolValue MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue
); );
} }
// TODO [ ] Issue #868 // TODO [ ] Issue #868
@@ -2105,6 +2142,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
false, false,
false, false,
false, false,
false,
false false
); );
} }
@@ -2330,6 +2368,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// <param name="joinMap"></param> /// <param name="joinMap"></param>
public void LinkZoomRoomToApi(BasicTriList trilist, ZoomRoomJoinMap joinMap) public void LinkZoomRoomToApi(BasicTriList trilist, ZoomRoomJoinMap joinMap)
{ {
var recordingCodec = this as IHasMeetingRecordingWithPrompt;
if (recordingCodec != null)
{
trilist.SetSigFalseAction(joinMap.StartRecording.JoinNumber, () => recordingCodec.StartRecording());
trilist.SetSigFalseAction(joinMap.StopRecording.JoinNumber, () => recordingCodec.StopRecording());
recordingCodec.MeetingIsRecordingFeedback.LinkInputSig(trilist.BooleanInput[joinMap.StartRecording.JoinNumber]);
recordingCodec.MeetingIsRecordingFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.StopRecording.JoinNumber]);
trilist.SetSigFalseAction(joinMap.RecordingPromptAgree.JoinNumber, () => recordingCodec.RecordingPromptAcknowledgement(true));
trilist.SetSigFalseAction(joinMap.RecordingPromptDisagree.JoinNumber, () => recordingCodec.RecordingPromptAcknowledgement(false));
recordingCodec.RecordConsentPromptIsVisible.LinkInputSig(trilist.BooleanInput[joinMap.RecordConsentPromptIsVisible.JoinNumber]);
}
var layoutsCodec = this as IHasZoomRoomLayouts; var layoutsCodec = this as IHasZoomRoomLayouts;
if (layoutsCodec != null) if (layoutsCodec != null)
{ {
@@ -2416,29 +2469,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}); });
layoutSizeCodec.SelfviewPipSizeFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetSelfviewPipSize.JoinNumber]); layoutSizeCodec.SelfviewPipSizeFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetSelfviewPipSize.JoinNumber]);
} }
PasswordRequired += (device, args) =>
{
if (args.LoginAttemptCancelled)
{
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, false);
return;
}
if (!string.IsNullOrEmpty(args.Message))
{
trilist.SetString(joinMap.PasswordPromptMessage.JoinNumber, args.Message);
}
if (args.LoginAttemptFailed)
{
trilist.SetBool(joinMap.PasswordLoginFailed.JoinNumber, true);
return;
}
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, true);
};
MeetingInfoChanged += (device, args) => MeetingInfoChanged += (device, args) =>
{ {
@@ -2464,6 +2495,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
trilist.SetStringSigAction(joinMap.SubmitPassword.JoinNumber, SubmitPassword); trilist.SetStringSigAction(joinMap.SubmitPassword.JoinNumber, SubmitPassword);
trilist.SetStringSigAction(joinMap.CancelPasswordPrompt.JoinNumber,
delegate { OnPasswordRequired(false, false, true, ""); });
PasswordRequired += (devices, args) => PasswordRequired += (devices, args) =>
{ {
if (args.LoginAttemptCancelled) if (args.LoginAttemptCancelled)
@@ -2696,27 +2729,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
try try
{ {
Debug.Console(2, this, "OnDirectoryResultReturned"); Debug.Console(2, this, "OnDirectoryResultReturned. Result has {0} contacts", result.Contacts.Count);
var directoryResult = new CodecDirectory(); CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate();
var directoryResult = result;
var directoryIsRoot = CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false;
// If result is Root, create a copy and filter out contacts whose parent folder is not root // If result is Root, create a copy and filter out contacts whose parent folder is not root
if (!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue) //if (!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue)
{ //{
Debug.Console(2, this, "Filtering DirectoryRoot to remove contacts for display"); // Debug.Console(2, this, "Filtering DirectoryRoot to remove contacts for display");
directoryResult.ResultsFolderId = result.ResultsFolderId; // directoryResult.ResultsFolderId = result.ResultsFolderId;
directoryResult.AddFoldersToDirectory(result.Folders); // directoryResult.AddFoldersToDirectory(result.Folders);
directoryResult.AddContactsToDirectory( // directoryResult.AddContactsToDirectory(
result.Contacts.Where((c) => c.ParentFolderId == result.ResultsFolderId).ToList()); // result.Contacts.Where((c) => c.ParentFolderId == result.ResultsFolderId).ToList());
} //}
else //else
{ //{
directoryResult = result; // directoryResult = result;
} //}
Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0}", Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0} Contact Count: {1}",
!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); directoryIsRoot, directoryResult.Contacts.Count);
// This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology // This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology
var handler = DirectoryResultReturned; var handler = DirectoryResultReturned;
@@ -2725,9 +2761,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
handler(this, new DirectoryEventArgs handler(this, new DirectoryEventArgs
{ {
Directory = directoryResult, Directory = directoryResult,
DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue DirectoryIsOnRoot = directoryIsRoot
}); });
} }
} }
catch (Exception e) catch (Exception e)
{ {
@@ -2758,14 +2796,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
continue; continue;
} }
var camera = new ZoomRoomCamera(cam.id, cam.Name, this); var existingCam = Cameras.FirstOrDefault((c) => c.Key.Equals(cam.id));
Cameras.Add(camera); if (existingCam == null)
{
var camera = new ZoomRoomCamera(cam.id, cam.Name, this);
if (cam.Selected) Cameras.Add(camera);
{
SelectedCamera = camera; if (cam.Selected)
} {
SelectedCamera = camera;
}
}
} }
if (IsInCall) if (IsInCall)
@@ -2798,6 +2841,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
SendText(string.Format("zCommand Call HostChange Id: {0}", userId)); SendText(string.Format("zCommand Call HostChange Id: {0}", userId));
} }
public void AdmitParticipantFromWaitingRoom(int userId)
{
SendText(string.Format("zCommand Call Admit Participant Id: {0}", userId));
}
#endregion #endregion
#region IHasParticipantAudioMute Members #region IHasParticipantAudioMute Members
@@ -3311,6 +3359,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
Debug.Console(2, this, "Password Submitted: {0}", password); Debug.Console(2, this, "Password Submitted: {0}", password);
Dial(_lastDialedMeetingNumber, password); Dial(_lastDialedMeetingNumber, password);
OnPasswordRequired(false, false, true, "");
} }
void OnPasswordRequired(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) void OnPasswordRequired(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message)
@@ -3408,18 +3457,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
#endregion #endregion
#region IHasMeetingRecording Members #region IHasMeetingRecordingWithPrompt Members
public BoolFeedback MeetingIsRecordingFeedback { get; private set; } public BoolFeedback MeetingIsRecordingFeedback { get; private set; }
bool _recordConsentPromptIsVisible;
public BoolFeedback RecordConsentPromptIsVisible { get; private set; }
public void RecordingPromptAcknowledgement(bool agree)
{
var command = string.Format("zCommand Agree Recording: {0}", agree ? "on" : "off");
//Debug.Console(2, this, "Sending agree: {0} {1}", agree, command);
SendText(command);
}
public void StartRecording() public void StartRecording()
{ {
SendText(string.Format("Command Call Record Enable: on")); SendText(string.Format("zCommand Call Record Enable: on"));
} }
public void StopRecording() public void StopRecording()
{ {
SendText(string.Format("Command Call Record Enable: off")); SendText(string.Format("zCommand Call Record Enable: off"));
} }
public void ToggleRecording() public void ToggleRecording()

View File

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

View File

@@ -23,6 +23,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("CancelPasswordPrompt")]
public JoinDataComplete CancelPasswordPrompt = new JoinDataComplete(
new JoinData
{
JoinNumber = 7,
JoinSpan = 1
},
new JoinMetadata
{
Description = "cancels password prompt",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868 // TODO [ ] Issue #868
[JoinName("PasswordIncorrect")] [JoinName("PasswordIncorrect")]
public JoinDataComplete PasswordIncorrect = new JoinDataComplete( public JoinDataComplete PasswordIncorrect = new JoinDataComplete(
@@ -295,7 +309,77 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Description = "Toggles the selfview pip size, (aka layout size)", Description = "Toggles the selfview pip size, (aka layout size)",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("StartRecording")]
public JoinDataComplete StartRecording = new JoinDataComplete(
new JoinData
{
JoinNumber = 241,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to start the Meeting Recording. FB high if meeting is currently recording",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("StopRecording")]
public JoinDataComplete StopRecording = new JoinDataComplete(
new JoinData
{
JoinNumber = 242,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to stop the Meeting Recording. FB high if meeting is currently NOT recording",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RecordConsentPromptIsVisible")]
public JoinDataComplete RecordConsentPromptIsVisible = new JoinDataComplete(
new JoinData
{
JoinNumber = 243,
JoinSpan = 1
},
new JoinMetadata
{
Description = "When high, indicates that the recording consent prompt is visible on the ZoomRoom UI",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RecordingPromptAgree")]
public JoinDataComplete RecordingPromptAgree = new JoinDataComplete(
new JoinData
{
JoinNumber = 244,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to agree to consent for meeting recording",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RecordingPromptDisagree")]
public JoinDataComplete RecordingPromptDisagree = new JoinDataComplete(
new JoinData
{
JoinNumber = 245,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to disagree to consent for meeting recording",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
//[JoinName("ParticipantAudioMuteToggleStart")] //[JoinName("ParticipantAudioMuteToggleStart")]
//public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( //public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete(

View File

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