From 6dd882b1a0d56f57f9229f5e958501a378809442 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 10 Nov 2021 13:49:43 -0700 Subject: [PATCH 001/202] feat(essentials): Adds hold/resume/duration features to call status --- .../Codec/CodecActiveCallItem.cs | 20 ++++++---- .../Codec/IHasCallHold.cs | 23 +++++++++++ .../Essentials Devices Common.csproj | 1 + .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 36 +++++++++++++++-- .../VideoCodec/CiscoCodec/xStatus.cs | 40 +++++++++++++++++-- 5 files changed, 106 insertions(+), 14 deletions(-) create mode 100644 essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasCallHold.cs diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/CodecActiveCallItem.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/CodecActiveCallItem.cs index 75c4fc1a..d1dbdf5f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/CodecActiveCallItem.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/CodecActiveCallItem.cs @@ -12,34 +12,40 @@ namespace PepperDash.Essentials.Devices.Common.Codec { public class CodecActiveCallItem { - [JsonProperty("name")] + [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; set; } - [JsonProperty("number")] + [JsonProperty("number", NullValueHandling = NullValueHandling.Ignore)] public string Number { get; set; } - [JsonProperty("type")] + [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] [JsonConverter(typeof(StringEnumConverter))] public eCodecCallType Type { get; set; } - [JsonProperty("status")] + [JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)] [JsonConverter(typeof(StringEnumConverter))] public eCodecCallStatus Status { get; set; } - [JsonProperty("direction")] + [JsonProperty("direction", NullValueHandling = NullValueHandling.Ignore)] [JsonConverter(typeof(StringEnumConverter))] public eCodecCallDirection Direction { get; set; } - [JsonProperty("id")] + [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] public string Id { get; set; } + [JsonProperty("isOnHold", NullValueHandling = NullValueHandling.Ignore)] + public bool IsOnHold { get; set; } + + [JsonProperty("duration", NullValueHandling = NullValueHandling.Ignore)] + public TimeSpan Duration { get; set; } + //public object CallMetaData { get; set; } /// /// Returns true when this call is any status other than /// Unknown, Disconnected, Disconnecting /// - [JsonProperty("isActiveCall")] + [JsonProperty("isActiveCall", NullValueHandling = NullValueHandling.Ignore)] public bool IsActiveCall { get diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasCallHold.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasCallHold.cs new file mode 100644 index 00000000..78211841 --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasCallHold.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Essentials.Devices.Common.Codec +{ + public interface IHasCallHold + { + /// + /// Put the specified call on hold + /// + /// + void HoldCall(CodecActiveCallItem activeCall); + + /// + /// Resume the specified call + /// + /// + void ResumeCall(CodecActiveCallItem activeCall); + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index 1fcffff2..b3f78d0e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -108,6 +108,7 @@ + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 2d3645f0..99021350 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -30,7 +30,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco IHasScheduleAwareness, IOccupancyStatusProvider, IHasCodecLayouts, IHasCodecSelfView, ICommunicationMonitor, IRouting, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets, IHasExternalSourceSwitching, IHasBranding, IHasCameraOff, IHasCameraMute, IHasDoNotDisturbMode, - IHasHalfWakeMode + IHasHalfWakeMode, IHasCallHold { private bool _externalSourceChangeRequested; @@ -847,6 +847,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco changeDetected = true; } } + if(call.Duration != null) + { + if(!string.IsNullOrEmpty(call.Duration.Value)) + { + tempActiveCall.Duration = call.Duration.DurationValue; + changeDetected = true; + } + } + if(call.PlacedOnHold != null) + { + tempActiveCall.IsOnHold = call.PlacedOnHold.BoolValue; + changeDetected = true; + } if (changeDetected) { @@ -865,7 +878,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco Name = call.DisplayName.Value, Number = call.RemoteNumber.Value, Type = CodecCallType.ConvertToTypeEnum(call.CallType.Value), - Direction = CodecCallDirection.ConvertToDirectionEnum(call.Direction.Value) + Direction = CodecCallDirection.ConvertToDirectionEnum(call.Direction.Value), + Duration = call.Duration.DurationValue, + IsOnHold = call.PlacedOnHold.BoolValue, }; // Add it to the ActiveCalls List @@ -1348,7 +1363,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { SendText(string.Format("xCommand Dial Number: \"{0}\" Protocol: {1} CallRate: {2} CallType: {3} BookingId: {4}", number, protocol, callRate, callType, meetingId)); } - + + public override void EndCall(CodecActiveCallItem activeCall) { SendText(string.Format("xCommand Call Disconnect CallId: {0}", activeCall.Id)); @@ -1372,6 +1388,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco SendText("xCommand Call Reject"); } + #region IHasCallHold Members + + public void HoldCall(CodecActiveCallItem activeCall) + { + SendText(string.Format("xCommand Call Hold CallId: {0}", activeCall.Id)); + } + + public void ResumeCall(CodecActiveCallItem activeCall) + { + SendText(string.Format("xCommand Call Resume CallId: {0}", activeCall.Id)); + } + + #endregion + public override void SendDtmf(string s) { SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", GetCallId(), s)); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index 29b9f260..eadc4c32 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -1949,9 +1949,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public string Value { get; set; } } - public class Duration + public class Duration : ValueProperty { - public string Value { get; set; } + private string _Value; + + public string Value + { + get + { + return _Value; + } + set + { + _Value = value; + OnValueChanged(); + } + } + + public TimeSpan DurationValue + { + get + { + return new TimeSpan(0, 0, Int32.Parse(_Value)); + } + } } public class FacilityServiceId @@ -1964,9 +1985,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public string Value { get; set; } } - public class PlacedOnHold + public class PlacedOnHold : ValueProperty { - public string Value { get; set; } + public bool BoolValue { get; private set; } + + public string Value + { + set + { + // If the incoming value is "True" it sets the BoolValue true, otherwise sets it false + BoolValue = value == "True"; + OnValueChanged(); + } + } } public class Protocol @@ -2014,6 +2045,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { CallType = new CallType(); Status = new Status2(); + Duration = new Duration(); } } From dc53ce42e71cd40f81352573387a0aa61a0e7913 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 10 Nov 2021 14:08:12 -0700 Subject: [PATCH 002/202] feat(essentials): Adds interface and implementation to join calls --- .../Essentials Devices Common.csproj | 1 + .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 19 ++++++++++++++++++- .../VideoCodec/Interfaces/IJoinCalls.cs | 16 ++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IJoinCalls.cs diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index b3f78d0e..3689bf61 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -130,6 +130,7 @@ + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 99021350..779fd310 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -30,7 +30,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco IHasScheduleAwareness, IOccupancyStatusProvider, IHasCodecLayouts, IHasCodecSelfView, ICommunicationMonitor, IRouting, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets, IHasExternalSourceSwitching, IHasBranding, IHasCameraOff, IHasCameraMute, IHasDoNotDisturbMode, - IHasHalfWakeMode, IHasCallHold + IHasHalfWakeMode, IHasCallHold, IJoinCalls { private bool _externalSourceChangeRequested; @@ -1400,6 +1400,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco SendText(string.Format("xCommand Call Resume CallId: {0}", activeCall.Id)); } + #endregion + #region IJoinCalls + + public void JoinCall(CodecActiveCallItem activeCall) + { + SendText(string.Format("xCommand Call Join CallId: {0}", activeCall.Id)); + } + + public void JoinAllCalls() + { + foreach (var call in ActiveCalls) + { + if(call.IsActiveCall) + JoinCall(call); + } + } + #endregion public override void SendDtmf(string s) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IJoinCalls.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IJoinCalls.cs new file mode 100644 index 00000000..b84db1e9 --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IJoinCalls.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +using PepperDash.Essentials.Devices.Common.Codec; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec +{ + public interface IJoinCalls + { + void JoinCall(CodecActiveCallItem activeCall); + void JoinAllCalls(); + } +} \ No newline at end of file From a043309bb1ec07d63c351296fb1fb228c406eaa8 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 10 Nov 2021 18:02:23 -0700 Subject: [PATCH 003/202] feat(essentials): More updates to add ringtone volume and focus near/far to bridge --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 42 +++++++++++++++++ .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 35 +++++++++++++++ .../VideoCodec/CiscoCodec/xConfiguration.cs | 45 ++++++++++++++++++- .../VideoCodec/CiscoCodec/xStatus.cs | 34 +++++++------- .../VideoCodec/VideoCodecBase.cs | 33 ++++++++++++++ 5 files changed, 170 insertions(+), 19 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index dcb66a2e..c83f6332 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -525,6 +525,48 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("CameraFocusNear")] + public JoinDataComplete CameraFocusNear = new JoinDataComplete( + new JoinData + { + JoinNumber = 117, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Focus Near", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraFocusFar")] + public JoinDataComplete CameraFocusFar = new JoinDataComplete( + new JoinData + { + JoinNumber = 118, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Focus Far", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraFocusAuto")] + public JoinDataComplete CameraFocusAuto = new JoinDataComplete( + new JoinData + { + JoinNumber = 119, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Auto Focus Trigger", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("CameraPresetSave")] public JoinDataComplete CameraPresetSave = new JoinDataComplete( new JoinData diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 779fd310..172c186c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -64,6 +64,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public BoolFeedback FarEndIsSharingContentFeedback { get; private set; } + public IntFeedback RingtoneVolumeFeedback { get; private set; } + private CodecCommandWithLabel CurrentSelfviewPipPosition; private CodecCommandWithLabel CurrentLocalLayout; @@ -324,6 +326,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco PresentationViewMaximizedFeedback = new BoolFeedback(() => CurrentPresentationView == "Maximized"); + RingtoneVolumeFeedback = new IntFeedback(() => CodecConfiguration.Configuration.Audio.SoundsAndAlerts.RingVolume.Volume); + Communication = comm; if (props.CommunicationMonitorProperties != null) @@ -436,6 +440,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = FarEndIsSharingContentFeedback.FireUpdate; CodecStatus.Status.Conference.DoNotDisturb.ValueChangedAction = DoNotDisturbModeIsOnFeedback.FireUpdate; + CodecConfiguration.Configuration.Audio.SoundsAndAlerts.RingVolume.ValueChangedAction = RingtoneVolumeFeedback.FireUpdate; + try { CodecStatus.Status.Video.Input.MainVideoMute.ValueChangedAction = CameraIsOffFeedback.FireUpdate; @@ -1419,11 +1425,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco #endregion + /// + /// Sends tones to the last connected call + /// + /// public override void SendDtmf(string s) { SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", GetCallId(), s)); } + /// + /// Sends tones to a specific call + /// + /// + /// + public void SendDtmf(string s, CodecActiveCallItem activeCall) + { + SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", activeCall.Id, s)); + } + public void SelectPresentationSource(int source) { PresentationSource = source; @@ -1431,6 +1451,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco StartSharing(); } + /// + /// Sets the ringtone volume level + /// + /// level from 0 - 100 in increments of 5 + public void SetRingtoneVolume(int volume) + { + SendText(string.Format("xConfiguration Audio SoundsAndAlerts RingVolume: [0]", volume)); + } + /// /// Select source 1 as the presetnation source /// @@ -1447,6 +1476,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco SelectPresentationSource(3); } + + /// /// Starts presentation sharing /// @@ -1473,6 +1504,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco SendText("xCommand Presentation Stop"); } + + public override void PrivacyModeOn() { SendText("xCommand Audio Microphones Mute"); @@ -1601,6 +1634,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco trilist.SetSigFalseAction(joinMap.DeactivateStandby.JoinNumber, () => halfwakeCodec.StandbyDeactivate()); trilist.SetSigFalseAction(joinMap.ActivateHalfWakeMode.JoinNumber, () => halfwakeCodec.HalfwakeActivate()); } + + // TODO: Add mechanism to select a call instance to be able to direct DTMF tones to... } /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs index 8ae9e643..e6ee8e4d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs @@ -112,16 +112,46 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public string Value { get; set; } } - public class RingVolume + public class RingVolume : ValueProperty { public string valueSpaceRef { get; set; } - public string Value { get; set; } + + string _Value; + + /// + /// Sets Value and triggers the action when set + /// + public string Value + { + get + { + return _Value; + } + set + { + _Value = value; + OnValueChanged(); + } + } + + public int Volume + { + get + { + return Int32.Parse(_Value); + } + } } public class SoundsAndAlerts { public RingTone RingTone { get; set; } public RingVolume RingVolume { get; set; } + + public SoundsAndAlerts() + { + RingVolume = new RingVolume(); + } } public class Audio @@ -131,6 +161,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public Microphones Microphones { get; set; } public Output Output { get; set; } public SoundsAndAlerts SoundsAndAlerts { get; set; } + + + public Audio() + { + SoundsAndAlerts = new SoundsAndAlerts(); + } } public class DefaultMode @@ -1797,6 +1833,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public UserInterface UserInterface { get; set; } public UserManagement UserManagement { get; set; } public Video2 Video { get; set; } + + public Configuration() + { + Audio = new Audio(); + } } public class RootObject diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index eadc4c32..ca98c1fc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -12,28 +12,28 @@ using PepperDash.Essentials.Devices.Common.VideoCodec.CiscoCodec; namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { + // Helper Classes for Proerties + public abstract class ValueProperty + { + /// + /// Triggered when Value is set + /// + public Action ValueChangedAction { get; set; } + + protected void OnValueChanged() + { + var a = ValueChangedAction; + if (a != null) + a(); + } + + } + /// /// This class exists to capture serialized data sent back by a Cisco codec in JSON output mode /// public class CiscoCodecStatus { - // Helper Classes for Proerties - public abstract class ValueProperty - { - /// - /// Triggered when Value is set - /// - public Action ValueChangedAction { get; set; } - - protected void OnValueChanged() - { - var a = ValueChangedAction; - if (a != null) - a(); - } - - } - public class ConnectionStatus { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 2549bea0..84900293 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1201,6 +1201,39 @@ ScreenIndexIsPinnedTo: {8} (a{17}) else camera.ZoomStop(); }); + + trilist.SetBoolSigAction(joinMap.CameraFocusNear.JoinNumber, (b) => + { + if (codec.SelectedCamera == null) return; + var camera = codec.SelectedCamera as IHasCameraFocusControl; + + if (camera == null) return; + + if (b) camera.FocusNear(); + else camera.FocusStop(); + }); + + trilist.SetBoolSigAction(joinMap.CameraFocusFar.JoinNumber, (b) => + { + if (codec.SelectedCamera == null) return; + var camera = codec.SelectedCamera as IHasCameraFocusControl; + + if (camera == null) return; + + if (b) camera.FocusFar(); + else camera.FocusStop(); + }); + + trilist.SetSigFalseAction(joinMap.CameraFocusAuto.JoinNumber, () => + { + if (codec.SelectedCamera == null) return; + var camera = codec.SelectedCamera as IHasCameraFocusControl; + + if (camera == null) return; + + camera.TriggerAutoFocus(); + }); + //Camera Select trilist.SetUShortSigAction(joinMap.CameraNumberSelect.JoinNumber, (i) => { From 8aae23db9e2a70d36c16d12b7a3953629fcd64f9 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 11 Nov 2021 16:54:03 -0700 Subject: [PATCH 004/202] feat(essentials): #865 Updates to Bridging Adds ability to end individual calls, report connected call count, report call duration and hold status, send DTMF tones to individual call index and select far end presets --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 80 +++++++++++++- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 14 ++- .../VideoCodec/CiscoCodec/RoomPresets.cs | 2 + .../VideoCodec/MockVC/MockVC.cs | 5 + .../VideoCodec/VideoCodecBase.cs | 102 +++++++++++++++--- 5 files changed, 179 insertions(+), 24 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index c83f6332..d8610047 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -20,6 +20,20 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("SendDtmfToSpecificCallIndex")] + public JoinDataComplete SendDtmfToSpecificCallIndex = new JoinDataComplete( + new JoinData + { + JoinNumber = 10, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "If High, will send DTMF tones to the call set by SelectCall analog. If low sends DTMF tones to last connected call.", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("1")] public JoinDataComplete Dtmf1 = new JoinDataComplete( new JoinData @@ -188,8 +202,8 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("EndCall")] - public JoinDataComplete EndCall = new JoinDataComplete( + [JoinName("EndAllCalls")] + public JoinDataComplete EndAllCalls = new JoinDataComplete( new JoinData { JoinNumber = 24, @@ -197,7 +211,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Hang Up", + Description = "End All Calls", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); @@ -576,7 +590,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Save Selected Preset", + Description = "Pulse to save selected preset. FB will pulse for 3s when preset saved.", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); @@ -966,6 +980,48 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps #region Analog + [JoinName("SelectCall")] + public JoinDataComplete SelectCall = new JoinDataComplete( + new JoinData + { + JoinNumber = 24, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Sets the selected Call. Valid values 1-8", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("EndCall")] + public JoinDataComplete EndCall = new JoinDataComplete( + new JoinData + { + JoinNumber = 24, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "End a specific call by call index. Valid values 1-8", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("ConnectedCallCount")] + public JoinDataComplete ConnectedCallCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 25, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the number of currently connected calls", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + [JoinName("MinutesBeforeMeetingStart")] public JoinDataComplete MinutesBeforeMeetingStart = new JoinDataComplete( new JoinData @@ -1032,10 +1088,24 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps new JoinMetadata { Description = "Camera Preset Select", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + [JoinName("FarEndPresetSelect")] + public JoinDataComplete FarEndPresetSelect = new JoinDataComplete( + new JoinData + { + JoinNumber = 122, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Far End Preset Preset Select", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + [JoinName("ParticipantCount")] public JoinDataComplete ParticipantCount = new JoinDataComplete( new JoinData diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 172c186c..7b44b47a 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -1407,6 +1407,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } #endregion + #region IJoinCalls public void JoinCall(CodecActiveCallItem activeCall) @@ -1416,10 +1417,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public void JoinAllCalls() { + StringBuilder ids = new StringBuilder(); + foreach (var call in ActiveCalls) { - if(call.IsActiveCall) - JoinCall(call); + if (call.IsActiveCall) + { + ids.Append(string.Format(" CallId: {0}", call.Id)); + } + } + + if (ids.Length > 0) + { + SendText(string.Format("xCommand Call Join {0}", ids.ToString())); } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs index 1b456774..b6327d52 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs @@ -26,6 +26,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec void CodecRoomPresetSelect(int preset); void CodecRoomPresetStore(int preset, string description); + + void SelectFarEndPreset(int preset); } public static class RoomPresets diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs index 78302fcc..c47870ab 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs @@ -751,6 +751,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec SetConfig(Config); } + public void SelectFarEndPreset(int i) + { + Debug.Console(1, this, "Selecting Far End Preset: {0}", i); + } + #endregion protected override void CustomSetConfig(DeviceConfig config) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 84900293..5771d868 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -149,6 +149,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public abstract void AcceptCall(CodecActiveCallItem call); public abstract void RejectCall(CodecActiveCallItem call); public abstract void SendDtmf(string s); + public virtual void SendDtmf(string s, CodecActiveCallItem call) { } #endregion @@ -978,8 +979,21 @@ ScreenIndexIsPinnedTo: {8} (a{17}) trilist.SetSigFalseAction(joinMap.ManualDial.JoinNumber, () => Dial(trilist.StringOutput[joinMap.CurrentDialString.JoinNumber].StringValue)); - //End All calls for now - trilist.SetSigFalseAction(joinMap.EndCall.JoinNumber, EndAllCalls); + //End All calls + trilist.SetSigFalseAction(joinMap.EndAllCalls.JoinNumber, EndAllCalls); + + //End a specific call, specified by index + trilist.SetUShortSigAction(joinMap.EndCall.JoinNumber, (i) => + { + if (i > 0 && i <= 8) + { + var call = ActiveCalls[i - 1]; + if (call != null) + { + EndCall(call); + } + } + }); trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); @@ -998,6 +1012,8 @@ ScreenIndexIsPinnedTo: {8} (a{17}) } trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); + + trilist.SetUshort(joinMap.ConnectedCallCount.JoinNumber, (ushort)ActiveCalls.Count); }; } @@ -1018,6 +1034,7 @@ ScreenIndexIsPinnedTo: {8} (a{17}) break; //digitals tokenArray[arrayIndex] = new XSigDigitalToken(digitalIndex + 1, call.IsActiveCall); + tokenArray[arrayIndex + 1] = new XSigDigitalToken(digitalIndex + 2, call.IsOnHold); //serials tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); @@ -1025,6 +1042,12 @@ ScreenIndexIsPinnedTo: {8} (a{17}) tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString()); tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 4, call.Type.ToString()); tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 5, call.Status.ToString()); + if(call.Duration != null) + { + // May need to verify correct string format here + var dur = string.Format("{0:c}", call.Duration); + tokenArray[arrayIndex + 6] = new XSigSerialToken(stringIndex + 6, dur); + } arrayIndex += offset; stringIndex += maxStrings; @@ -1034,13 +1057,16 @@ ScreenIndexIsPinnedTo: {8} (a{17}) { //digitals tokenArray[arrayIndex] = new XSigDigitalToken(digitalIndex + 1, false); + tokenArray[arrayIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); - //serials + + //serials tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty); tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty); tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty); tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 4, String.Empty); tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 5, String.Empty); + tokenArray[arrayIndex + 6] = new XSigSerialToken(stringIndex + 6, String.Empty); arrayIndex += offset; stringIndex += maxStrings; @@ -1052,20 +1078,56 @@ ScreenIndexIsPinnedTo: {8} (a{17}) private void LinkVideoCodecDtmfToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { - trilist.SetSigFalseAction(joinMap.Dtmf0.JoinNumber, () => SendDtmf("0")); - trilist.SetSigFalseAction(joinMap.Dtmf1.JoinNumber, () => SendDtmf("1")); - trilist.SetSigFalseAction(joinMap.Dtmf2.JoinNumber, () => SendDtmf("2")); - trilist.SetSigFalseAction(joinMap.Dtmf3.JoinNumber, () => SendDtmf("3")); - trilist.SetSigFalseAction(joinMap.Dtmf4.JoinNumber, () => SendDtmf("4")); - trilist.SetSigFalseAction(joinMap.Dtmf5.JoinNumber, () => SendDtmf("5")); - trilist.SetSigFalseAction(joinMap.Dtmf6.JoinNumber, () => SendDtmf("6")); - trilist.SetSigFalseAction(joinMap.Dtmf7.JoinNumber, () => SendDtmf("7")); - trilist.SetSigFalseAction(joinMap.Dtmf8.JoinNumber, () => SendDtmf("8")); - trilist.SetSigFalseAction(joinMap.Dtmf9.JoinNumber, () => SendDtmf("9")); - trilist.SetSigFalseAction(joinMap.DtmfStar.JoinNumber, () => SendDtmf("*")); - trilist.SetSigFalseAction(joinMap.DtmfPound.JoinNumber, () => SendDtmf("#")); + trilist.SetSigFalseAction(joinMap.Dtmf0.JoinNumber, () => SendDtmfAction("0", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf1.JoinNumber, () => SendDtmfAction("1", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf2.JoinNumber, () => SendDtmfAction("2", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf3.JoinNumber, () => SendDtmfAction("3", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf4.JoinNumber, () => SendDtmfAction("4", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf5.JoinNumber, () => SendDtmfAction("5", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf6.JoinNumber, () => SendDtmfAction("6", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf7.JoinNumber, () => SendDtmfAction("7", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf8.JoinNumber, () => SendDtmfAction("8", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf9.JoinNumber, () => SendDtmfAction("9", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.DtmfStar.JoinNumber, () => SendDtmfAction("*", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.DtmfPound.JoinNumber, () => SendDtmfAction("#", trilist, joinMap)); } + /// + /// Sends the specified string as a DTMF command. + /// Reads the value of the SendDtmfToSpecificCallInstance digital join and SelectCall analog join to determine + /// Whther to send to a specific call index or to the last connected call + /// + /// + /// + /// + private void SendDtmfAction(string s, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + if (!trilist.GetBool(joinMap.SendDtmfToSpecificCallIndex.JoinNumber)) + { + SendDtmf(s); + } + else + { + var callIndex = trilist.GetUshort(joinMap.SelectCall.JoinNumber); + if (callIndex > 0 && callIndex <= 8) + { + var call = ActiveCalls[callIndex - 1]; + if (call != null && call.IsActiveCall) + { + SendDtmf(s, call); + } + else + { + Debug.Console(0, this, "Warning: No call found at index {0} or call is not active.", callIndex); + } + } + else + { + Debug.Console(0, this, "Warning: Invalid call index specified. Please use a value of 1-8."); + } + } + } + private void LinkVideoCodecCameraLayoutsToApi(IHasCodecLayouts codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { trilist.SetSigFalseAction(joinMap.CameraLayout.JoinNumber, codec.LocalLayoutToggle); @@ -1288,10 +1350,16 @@ ScreenIndexIsPinnedTo: {8} (a{17}) trilist.SetUShortSigAction(joinMap.CameraPresetSelect.JoinNumber, (i) => { presetCodec.CodecRoomPresetSelect(i); - - trilist.SetUshort(joinMap.CameraPresetSelect.JoinNumber, i); }); + + // Far End Presets + trilist.SetUShortSigAction(joinMap.FarEndPresetSelect.JoinNumber, (i) => + { + presetCodec.SelectFarEndPreset(i); + }); + + trilist.SetSigFalseAction(joinMap.CameraPresetSave.JoinNumber, () => { From 0ff29695e73f388c685879ffa8b2407eb5dc9b3a Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 11 Nov 2021 21:05:57 -0700 Subject: [PATCH 005/202] feat(essentials): #865 Updates join map and bridge for new features Adds control and feedback for presentation source Updates camera setup, selection and feedback Adds ringtone volume control/feedback Adds call hold/resume/join control to bridge Adds new config properties for camera info --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 115 +++++++- .../VideoCodec/CiscoCodec/CiscoCamera.cs | 2 +- .../CiscoCodec/CiscoCodecJoinMap.cs | 56 ++++ .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 270 ++++++++++++------ .../CiscoSparkCodecPropertiesConfig.cs | 20 +- .../VideoCodec/CiscoCodec/xStatus.cs | 37 ++- .../VideoCodec/VideoCodecBase.cs | 108 ++++++- 7 files changed, 490 insertions(+), 118 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index d8610047..a0729352 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -342,6 +342,48 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("EndCallStart")] + public JoinDataComplete EndCallStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 81, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "End a specific call by call index. ", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("JoinAllCalls")] + public JoinDataComplete JoinAllCalls = new JoinDataComplete( + new JoinData + { + JoinNumber = 90, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "End a specific call by call index. ", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("JoinCallStart")] + public JoinDataComplete JoinCallStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 91, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "End a specific call by call index. ", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("DirectorySearchBusy")] public JoinDataComplete DirectorySearchBusy = new JoinDataComplete( new JoinData @@ -931,6 +973,34 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("HoldCallsStart")] + public JoinDataComplete HoldCallsStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 221, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Holds Call at specified index", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ResumeCallsStart")] + public JoinDataComplete ResumeCallsStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 231, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Resume Call at specified index", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("ParticipantAudioMuteToggleStart")] public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( new JoinData @@ -989,24 +1059,11 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Sets the selected Call. Valid values 1-8", + Description = "Sets the selected Call for DTMF commands. Valid values 1-8", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); - [JoinName("EndCall")] - public JoinDataComplete EndCall = new JoinDataComplete( - new JoinData - { - JoinNumber = 24, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "End a specific call by call index. Valid values 1-8", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); [JoinName("ConnectedCallCount")] public JoinDataComplete ConnectedCallCount = new JoinDataComplete( @@ -1045,11 +1102,25 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Camera Number Select/FB", + Description = "Camera Number Select/FB. 1 based index. Valid range is 1 to the value reported by CameraCount.", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("CameraCount")] + public JoinDataComplete CameraCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 61, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the number of cameras", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + [JoinName("DirectoryRowCount")] public JoinDataComplete DirectoryRowCount = new JoinDataComplete( new JoinData @@ -1323,6 +1394,20 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); + [JoinName("CameraNamesFb")] + public JoinDataComplete CameraNamesFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 161, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Camera Name Fb", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + [JoinName("CurrentSource")] public JoinDataComplete CurrentSource = new JoinDataComplete( new JoinData diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCamera.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCamera.cs index 6f68b369..67312df8 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCamera.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCamera.cs @@ -116,7 +116,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// /// The ID of the camera on the codec /// - protected uint CameraId { get; private set; } + public uint CameraId { get; private set; } /// /// Valid range 1-15 diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecJoinMap.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecJoinMap.cs index e4945ce8..44256ca4 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecJoinMap.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecJoinMap.cs @@ -9,6 +9,34 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { #region Digital + [JoinName("PresentationLocalOnly")] + public JoinDataComplete PresentationLocalOnly = new JoinDataComplete( + new JoinData + { + JoinNumber = 205, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Presentation Local Only Feedback", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("PresentationLocalRemote")] + public JoinDataComplete PresentationLocalRemote = new JoinDataComplete( + new JoinData + { + JoinNumber = 206, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Presentation Local Only Feedback", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("ActivateDoNotDisturbMode")] public JoinDataComplete ActivateDoNotDisturbMode = new JoinDataComplete( new JoinData @@ -112,6 +140,34 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco #region Analog + [JoinName("RingtoneVolume")] + public JoinDataComplete RingtoneVolume = new JoinDataComplete( + new JoinData + { + JoinNumber = 21, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Ringtone volume set/FB. Valid values are 0 - 100 in increments of 5 (5, 10, 15, 20, etc.)", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("PresentationSource")] + public JoinDataComplete PresentationSource = new JoinDataComplete( + new JoinData + { + JoinNumber = 201, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Presentation set/FB. Valid values are 0 - 6 depending on the codec model.", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + #endregion diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 7b44b47a..4c842f22 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -42,11 +42,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public StatusMonitorBase CommunicationMonitor { get; private set; } - private GenericQueue ReceiveQueue; + private GenericQueue _receiveQueue; public BoolFeedback PresentationViewMaximizedFeedback { get; private set; } - string CurrentPresentationView; + private string _currentPresentationView; public BoolFeedback RoomIsOccupiedFeedback { get; private set; } @@ -66,9 +66,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public IntFeedback RingtoneVolumeFeedback { get; private set; } - private CodecCommandWithLabel CurrentSelfviewPipPosition; + private CodecCommandWithLabel _currentSelfviewPipPosition; - private CodecCommandWithLabel CurrentLocalLayout; + private CodecCommandWithLabel _currentLocalLayout; /// /// List the available positions for the selfview PIP window @@ -167,7 +167,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { get { - return () => PresentationSourceKey; + return () => _presentationSourceKey; } } @@ -231,7 +231,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { get { - return () => CurrentSelfviewPipPosition.Label; + return () => _currentSelfviewPipPosition.Label; } } @@ -239,7 +239,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { get { - return () => CurrentLocalLayout.Label; + return () => _currentLocalLayout.Label; } } @@ -247,43 +247,58 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { get { - return () => CurrentLocalLayout.Label == "Prominent"; + return () => _currentLocalLayout.Label == "Prominent"; } } - private string CliFeedbackRegistrationExpression; + private string _cliFeedbackRegistrationExpression; - private CodecSyncState SyncState; + private CodecSyncState _syncState; public CodecPhonebookSyncState PhonebookSyncState { get; private set; } - private StringBuilder JsonMessage; + private StringBuilder _jsonMessage; - private bool JsonFeedbackMessageIsIncoming; + private bool _jsonFeedbackMessageIsIncoming; public bool CommDebuggingIsOn; string Delimiter = "\r\n"; + public IntFeedback PresentationSourceFeedback { get; private set; } + + public BoolFeedback PresentationSendingLocalOnlyFeedback { get; private set; } + + public BoolFeedback PresentationSendingLocalRemoteFeedback { get; private set; } + /// /// Used to track the current connector used for the presentation source /// - int PresentationSource; + private int _presentationSource; - string PresentationSourceKey; + /// + /// Used to track the connector that is desired to be the current presentation source (until the command is send) + /// + private int _desiredPresentationSource; - string PhonebookMode = "Local"; // Default to Local + private string _presentationSourceKey; - uint PhonebookResultsLimit = 255; // Could be set later by config. + private bool _presentationLocalOnly; - CTimer LoginMessageReceivedTimer; - CTimer RetryConnectionTimer; + private bool _presentationLocalRemote; + + private string _phonebookMode = "Local"; // Default to Local + + private uint _phonebookResultsLimit = 255; // Could be set later by config. + + private CTimer _loginMessageReceivedTimer; + private CTimer _retryConnectionTimer; // **___________________________________________________________________** // Timers to be moved to the global system timer at a later point.... - CTimer BookingsRefreshTimer; - CTimer PhonebookRefreshTimer; + private CTimer BookingsRefreshTimer; + private CTimer PhonebookRefreshTimer; // **___________________________________________________________________** public RoutingInputPort CodecOsdIn { get; private set; } @@ -302,11 +317,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco // Use the configured phonebook results limit if present if (props.PhonebookResultsLimit > 0) { - PhonebookResultsLimit = props.PhonebookResultsLimit; + _phonebookResultsLimit = props.PhonebookResultsLimit; } // The queue that will collect the repsonses in the order they are received - ReceiveQueue = new GenericQueue(this.Key + "-rxQueue", 25); + _receiveQueue = new GenericQueue(this.Key + "-rxQueue", 25); RoomIsOccupiedFeedback = new BoolFeedback(RoomIsOccupiedFeedbackFunc); PeopleCountFeedback = new IntFeedback(PeopleCountFeedbackFunc); @@ -324,10 +339,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco HalfWakeModeIsOnFeedback = new BoolFeedback(() => CodecStatus.Status.Standby.State.Value.ToLower() == "halfwake"); EnteringStandbyModeFeedback = new BoolFeedback(() => CodecStatus.Status.Standby.State.Value.ToLower() == "enteringstandby"); - PresentationViewMaximizedFeedback = new BoolFeedback(() => CurrentPresentationView == "Maximized"); + PresentationViewMaximizedFeedback = new BoolFeedback(() => _currentPresentationView == "Maximized"); RingtoneVolumeFeedback = new IntFeedback(() => CodecConfiguration.Configuration.Audio.SoundsAndAlerts.RingVolume.Volume); + PresentationSourceFeedback = new IntFeedback(() => _presentationSource); + PresentationSendingLocalOnlyFeedback = new BoolFeedback(() => _presentationLocalOnly); + PresentationSendingLocalRemoteFeedback = new BoolFeedback(() => _presentationLocalRemote); + Communication = comm; if (props.CommunicationMonitorProperties != null) @@ -346,13 +365,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco DeviceManager.AddDevice(CommunicationMonitor); - PhonebookMode = props.PhonebookMode; + _phonebookMode = props.PhonebookMode; - SyncState = new CodecSyncState(Key + "--Sync"); + _syncState = new CodecSyncState(Key + "--Sync"); PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); - SyncState.InitialSyncCompleted += new EventHandler(SyncState_InitialSyncCompleted); + _syncState.InitialSyncCompleted += new EventHandler(SyncState_InitialSyncCompleted); PortGather = new CommunicationGather(Communication, Delimiter); PortGather.IncludeDelimiter = true; @@ -399,7 +418,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco InputPorts.Add(HdmiIn3); OutputPorts.Add(HdmiOut1); - SetUpCameras(); + SetUpCameras(props.CameraInfo); CreateOsdSource(); @@ -589,7 +608,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco const string prefix = "xFeedback register "; - CliFeedbackRegistrationExpression = + _cliFeedbackRegistrationExpression = prefix + "/Configuration" + Delimiter + prefix + "/Status/Audio" + Delimiter + prefix + "/Status/Call" + Delimiter + @@ -651,12 +670,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco Debug.Console(1, this, "Socket status change {0}", e.Client.ClientStatus); if (e.Client.IsConnected) { - if(!SyncState.LoginMessageWasReceived) - LoginMessageReceivedTimer = new CTimer(o => DisconnectClientAndReconnect(), 5000); + if(!_syncState.LoginMessageWasReceived) + _loginMessageReceivedTimer = new CTimer(o => DisconnectClientAndReconnect(), 5000); } else { - SyncState.CodecDisconnected(); + _syncState.CodecDisconnected(); PhonebookSyncState.CodecDisconnected(); if (PhonebookRefreshTimer != null) @@ -679,7 +698,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco Communication.Disconnect(); - RetryConnectionTimer = new CTimer(o => Communication.Connect(), 2000); + _retryConnectionTimer = new CTimer(o => Communication.Connect(), 2000); //CrestronEnvironment.Sleep(2000); @@ -696,66 +715,66 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { if (CommDebuggingIsOn) { - if (!JsonFeedbackMessageIsIncoming) + if (!_jsonFeedbackMessageIsIncoming) Debug.Console(1, this, "RX: '{0}'", args.Text); } if (args.Text == "{" + Delimiter) // Check for the beginning of a new JSON message { - JsonFeedbackMessageIsIncoming = true; + _jsonFeedbackMessageIsIncoming = true; if (CommDebuggingIsOn) Debug.Console(1, this, "Incoming JSON message..."); - JsonMessage = new StringBuilder(); + _jsonMessage = new StringBuilder(); } else if (args.Text == "}" + Delimiter) // Check for the end of a JSON message { - JsonFeedbackMessageIsIncoming = false; + _jsonFeedbackMessageIsIncoming = false; - JsonMessage.Append(args.Text); + _jsonMessage.Append(args.Text); if (CommDebuggingIsOn) - Debug.Console(1, this, "Complete JSON Received:\n{0}", JsonMessage.ToString()); + Debug.Console(1, this, "Complete JSON Received:\n{0}", _jsonMessage.ToString()); // Enqueue the complete message to be deserialized - ReceiveQueue.Enqueue(new ProcessStringMessage(JsonMessage.ToString(), DeserializeResponse)); + _receiveQueue.Enqueue(new ProcessStringMessage(_jsonMessage.ToString(), DeserializeResponse)); return; } - if(JsonFeedbackMessageIsIncoming) + if(_jsonFeedbackMessageIsIncoming) { - JsonMessage.Append(args.Text); + _jsonMessage.Append(args.Text); //Debug.Console(1, this, "Building JSON:\n{0}", JsonMessage.ToString()); return; } - if (!SyncState.InitialSyncComplete) + if (!_syncState.InitialSyncComplete) { switch (args.Text.Trim().ToLower()) // remove the whitespace { case "*r login successful": { - SyncState.LoginMessageReceived(); + _syncState.LoginMessageReceived(); - if(LoginMessageReceivedTimer != null) - LoginMessageReceivedTimer.Stop(); + if(_loginMessageReceivedTimer != null) + _loginMessageReceivedTimer.Stop(); SendText("xPreferences outputmode json"); break; } case "xpreferences outputmode json": { - if (!SyncState.InitialStatusMessageWasReceived) + if (!_syncState.InitialStatusMessageWasReceived) SendText("xStatus"); break; } case "xfeedback register /event/calldisconnect": { - SyncState.FeedbackRegistered(); + _syncState.FeedbackRegistered(); break; } } @@ -801,11 +820,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco if (conference.Presentation.LocalInstance.Count > 0) { if (!string.IsNullOrEmpty(conference.Presentation.LocalInstance[0].ghost)) - PresentationSource = 0; + _presentationSource = 0; else if (conference.Presentation.LocalInstance[0].Source != null) { - PresentationSource = conference.Presentation.LocalInstance[0].Source.IntValue; + _presentationSource = conference.Presentation.LocalInstance[0].Source.IntValue; } + + _presentationLocalOnly = conference.Presentation.LocalInstance.Any((i) => i.SendingMode.LocalOnly); + _presentationLocalRemote = conference.Presentation.LocalInstance.Any((i) => i.SendingMode.LocalRemote); + + PresentationSourceFeedback.FireUpdate(); + PresentationSendingLocalOnlyFeedback.FireUpdate(); + PresentationSendingLocalRemoteFeedback.FireUpdate(); } // Check to see if this is a call status message received after the initial status message @@ -966,11 +992,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco JsonConvert.PopulateObject(response, CodecStatus); } - if (!SyncState.InitialStatusMessageWasReceived) + if (!_syncState.InitialStatusMessageWasReceived) { - SyncState.InitialStatusMessageReceived(); + _syncState.InitialStatusMessageReceived(); - if (!SyncState.InitialConfigurationMessageWasReceived) + if (!_syncState.InitialConfigurationMessageWasReceived) SendText("xConfiguration"); } } @@ -980,12 +1006,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco JsonConvert.PopulateObject(response, CodecConfiguration); - if (!SyncState.InitialConfigurationMessageWasReceived) + if (!_syncState.InitialConfigurationMessageWasReceived) { - SyncState.InitialConfigurationMessageReceived(); - if (!SyncState.FeedbackWasRegistered) + _syncState.InitialConfigurationMessageReceived(); + if (!_syncState.FeedbackWasRegistered) { - SendText(CliFeedbackRegistrationExpression); + SendText(_cliFeedbackRegistrationExpression); } } @@ -1158,7 +1184,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public override void ExecuteSwitch(object selector) { (selector as Action)(); - PresentationSourceKey = selector.ToString(); + _presentationSourceKey = selector.ToString(); } /// @@ -1168,7 +1194,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) { ExecuteSwitch(inputSelector); - PresentationSourceKey = inputSelector.ToString(); + _presentationSourceKey = inputSelector.ToString(); } @@ -1247,13 +1273,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco private void GetPhonebookFolders() { // Get Phonebook Folders (determine local/corporate from config, and set results limit) - SendText(string.Format("xCommand Phonebook Search PhonebookType: {0} ContactType: Folder", PhonebookMode)); + SendText(string.Format("xCommand Phonebook Search PhonebookType: {0} ContactType: Folder", _phonebookMode)); } private void GetPhonebookContacts() { // Get Phonebook Folders (determine local/corporate from config, and set results limit) - SendText(string.Format("xCommand Phonebook Search PhonebookType: {0} ContactType: Contact Limit: {1}", PhonebookMode, PhonebookResultsLimit)); + SendText(string.Format("xCommand Phonebook Search PhonebookType: {0} ContactType: Contact Limit: {1}", _phonebookMode, _phonebookResultsLimit)); } /// @@ -1262,7 +1288,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// public void SearchDirectory(string searchString) { - SendText(string.Format("xCommand Phonebook Search SearchString: \"{0}\" PhonebookType: {1} ContactType: Contact Limit: {2}", searchString, PhonebookMode, PhonebookResultsLimit)); + SendText(string.Format("xCommand Phonebook Search SearchString: \"{0}\" PhonebookType: {1} ContactType: Contact Limit: {2}", searchString, _phonebookMode, _phonebookResultsLimit)); } /// @@ -1271,7 +1297,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// public void GetDirectoryFolderContents(string folderId) { - SendText(string.Format("xCommand Phonebook Search FolderId: {0} PhonebookType: {1} ContactType: Any Limit: {2}", folderId, PhonebookMode, PhonebookResultsLimit)); + SendText(string.Format("xCommand Phonebook Search FolderId: {0} PhonebookType: {1} ContactType: Any Limit: {2}", folderId, _phonebookMode, _phonebookResultsLimit)); } /// @@ -1449,14 +1475,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// /// /// - public void SendDtmf(string s, CodecActiveCallItem activeCall) + public override void SendDtmf(string s, CodecActiveCallItem activeCall) { SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", activeCall.Id, s)); } public void SelectPresentationSource(int source) { - PresentationSource = source; + _desiredPresentationSource = source; StartSharing(); } @@ -1467,6 +1493,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// level from 0 - 100 in increments of 5 public void SetRingtoneVolume(int volume) { + if (volume < 0 || volume > 100) + { + Debug.Console(0, this, "Cannot set ringtone volume to '{0}'. Value must be between 0 - 100", volume); + return; + } + + if (volume % 5 != 0) + { + Debug.Console(0, this, "Cannot set ringtone volume to '{0}'. Value must be between 0 - 100 and a multiple of 5", volume); + return; + } + SendText(string.Format("xConfiguration Audio SoundsAndAlerts RingVolume: [0]", volume)); } @@ -1500,8 +1538,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco else sendingMode = "LocalOnly"; - if(PresentationSource > 0) - SendText(string.Format("xCommand Presentation Start PresentationSource: {0} SendingMode: {1}", PresentationSource, sendingMode)); + if (_desiredPresentationSource > 0) + SendText(string.Format("xCommand Presentation Start PresentationSource: {0} SendingMode: {1}", _desiredPresentationSource, sendingMode)); } /// @@ -1509,7 +1547,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// public override void StopSharing() { - PresentationSource = 0; + _desiredPresentationSource = 0; SendText("xCommand Presentation Stop"); } @@ -1645,7 +1683,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco trilist.SetSigFalseAction(joinMap.ActivateHalfWakeMode.JoinNumber, () => halfwakeCodec.HalfwakeActivate()); } - // TODO: Add mechanism to select a call instance to be able to direct DTMF tones to... + // Ringtone volume + trilist.SetUShortSigAction(joinMap.RingtoneVolume.JoinNumber, (u) => SetRingtoneVolume(u)); + RingtoneVolumeFeedback.LinkInputSig(trilist.UShortInput[joinMap.RingtoneVolume.JoinNumber]); + + // Presentation Source + trilist.SetUShortSigAction(joinMap.PresentationSource.JoinNumber, (u) => SelectPresentationSource(u)); + PresentationSourceFeedback.LinkInputSig(trilist.UShortInput[joinMap.PresentationSource.JoinNumber]); + + PresentationSendingLocalOnlyFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PresentationLocalOnly.JoinNumber]); + PresentationSendingLocalRemoteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PresentationLocalRemote.JoinNumber]); } /// @@ -1719,9 +1766,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// public void SelfviewPipPositionToggle() { - if (CurrentSelfviewPipPosition != null) + if (_currentSelfviewPipPosition != null) { - var nextPipPositionIndex = SelfviewPipPositions.IndexOf(CurrentSelfviewPipPosition) + 1; + var nextPipPositionIndex = SelfviewPipPositions.IndexOf(_currentSelfviewPipPosition) + 1; if (nextPipPositionIndex >= SelfviewPipPositions.Count) // Check if we need to loop back to the first item in the list nextPipPositionIndex = 0; @@ -1744,9 +1791,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// public void LocalLayoutToggle() { - if(CurrentLocalLayout != null) + if(_currentLocalLayout != null) { - var nextLocalLayoutIndex = LocalLayouts.IndexOf(CurrentLocalLayout) + 1; + var nextLocalLayoutIndex = LocalLayouts.IndexOf(_currentLocalLayout) + 1; if (nextLocalLayoutIndex >= LocalLayouts.Count) // Check if we need to loop back to the first item in the list nextLocalLayoutIndex = 0; @@ -1760,9 +1807,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// public void LocalLayoutToggleSingleProminent() { - if (CurrentLocalLayout != null) + if (_currentLocalLayout != null) { - if (CurrentLocalLayout.Label != "Prominent") + if (_currentLocalLayout.Label != "Prominent") LocalLayoutSet(LocalLayouts.FirstOrDefault(l => l.Label.Equals("Prominent"))); else LocalLayoutSet(LocalLayouts.FirstOrDefault(l => l.Label.Equals("Single"))); @@ -1776,11 +1823,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public void MinMaxLayoutToggle() { if (PresentationViewMaximizedFeedback.BoolValue) - CurrentPresentationView = "Minimized"; + _currentPresentationView = "Minimized"; else - CurrentPresentationView = "Maximized"; + _currentPresentationView = "Maximized"; - SendText(string.Format("xCommand Video PresentationView Set View: {0}", CurrentPresentationView)); + SendText(string.Format("xCommand Video PresentationView Set View: {0}", _currentPresentationView)); PresentationViewMaximizedFeedback.FireUpdate(); } @@ -1789,9 +1836,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// void ComputeSelfviewPipStatus() { - CurrentSelfviewPipPosition = SelfviewPipPositions.FirstOrDefault(p => p.Command.ToLower().Equals(CodecStatus.Status.Video.Selfview.PIPPosition.Value.ToLower())); + _currentSelfviewPipPosition = SelfviewPipPositions.FirstOrDefault(p => p.Command.ToLower().Equals(CodecStatus.Status.Video.Selfview.PIPPosition.Value.ToLower())); - if(CurrentSelfviewPipPosition != null) + if(_currentSelfviewPipPosition != null) SelfviewIsOnFeedback.FireUpdate(); } @@ -1800,9 +1847,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// void ComputeLocalLayout() { - CurrentLocalLayout = LocalLayouts.FirstOrDefault(l => l.Command.ToLower().Equals(CodecStatus.Status.Video.Layout.LayoutFamily.Local.Value.ToLower())); + _currentLocalLayout = LocalLayouts.FirstOrDefault(l => l.Command.ToLower().Equals(CodecStatus.Status.Video.Layout.LayoutFamily.Local.Value.ToLower())); - if (CurrentLocalLayout != null) + if (_currentLocalLayout != null) LocalLayoutFeedback.FireUpdate(); } @@ -1850,19 +1897,59 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// /// Builds the cameras List. Could later be modified to build from config data /// - void SetUpCameras() + void SetUpCameras(List cameraInfo) { // Add the internal camera Cameras = new List(); - var internalCamera = new CiscoSparkCamera(Key + "-camera1", "Near End", this, 1); + var camCount = CodecStatus.Status.Cameras.Camera.Count; - if(CodecStatus.Status.Cameras.Camera.Count > 0) - internalCamera.SetCapabilites(CodecStatus.Status.Cameras.Camera[0].Capabilities.Options.Value); + Debug.Console(0, this, "Codec reports {0} cameras", camCount); + + + // Deal with the case of 1 or no reported cameras + if (camCount <= 1) + { + var internalCamera = new CiscoSparkCamera(Key + "-camera1", "Near End", this, 1); + + if (CodecStatus.Status.Cameras.Camera[0] != null && CodecStatus.Status.Cameras.Camera[0].Capabilities != null) + { + internalCamera.SetCapabilites(CodecStatus.Status.Cameras.Camera[0].Capabilities.Options.Value); + } + + Cameras.Add(internalCamera); + DeviceManager.AddDevice(internalCamera); + } else - // Somehow subscribe to the event on the Options.Value property and update when it changes. + { + // Setup all the cameras + for (int i = 0; i < camCount; i++) + { + var cam = CodecStatus.Status.Cameras.Camera[i]; - Cameras.Add(internalCamera); + var id = (uint)i; + var name = string.Format("Camera {0}", id); + + // Check for a config object that matches the camera number + var camInfo = cameraInfo.FirstOrDefault(c => c.CameraNumber == i + 1); + if (camInfo != null) + { + id = (uint)camInfo.SourceId; + name = camInfo.Name; + } + + var key = string.Format("{0}-camera{1}", Key, id); + var camera = new CiscoSparkCamera(key, name, this, id); + + if (cam.Capabilities != null) + { + camera.SetCapabilites(cam.Capabilities.Options.Value); + } + + Cameras.Add(camera); + DeviceManager.AddDevice(camera); + } + } // Add the far end camera var farEndCamera = new CiscoFarEndCamera(Key + "-cameraFar", "Far End", this); @@ -1872,7 +1959,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco ControllingFarEndCameraFeedback = new BoolFeedback(() => SelectedCamera is IAmFarEndCamera); - DeviceManager.AddDevice(internalCamera); DeviceManager.AddDevice(farEndCamera); NearEndPresets = new List(15); @@ -1886,7 +1972,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco FarEndRoomPresets.Add(new CodecRoomPreset(i, label, true, false)); } - SelectedCamera = internalCamera; ; // call the method to select the camera and ensure the feedbacks get updated. + SelectedCamera = Cameras[0]; ; // call the method to select the camera and ensure the feedbacks get updated. } #region IHasCodecCameras Members @@ -1934,6 +2020,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } else Debug.Console(2, this, "Unable to select camera with key: '{0}'", key); + + var ciscoCam = camera as CiscoSparkCamera; + if (ciscoCam != null) + { + SendText(string.Format("xCommand Video Input SetMainVideoSource SourceId: {0}", ciscoCam.CameraId)); + } } public CameraBase FarEndCamera { get; private set; } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodecPropertiesConfig.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodecPropertiesConfig.cs index 1836bafb..7f36b0bf 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodecPropertiesConfig.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodecPropertiesConfig.cs @@ -50,8 +50,16 @@ namespace PepperDash.Essentials.Devices.Common.Codec public uint PhonebookResultsLimit { get; set; } [JsonProperty("UiBranding")] - public BrandingLogoProperties UiBranding { get; set; } + public BrandingLogoProperties UiBranding { get; set; } + [JsonProperty("cameraInfo")] + public List CameraInfo { get; set; } + + + public CiscoSparkCodecPropertiesConfig() + { + CameraInfo = new List(); + } } public class SharingProperties @@ -68,4 +76,14 @@ namespace PepperDash.Essentials.Devices.Common.Codec [JsonProperty("brandingUrl")] public string BrandingUrl { get; set; } } + + /// + /// Describes configuration information for the near end cameras + /// + public class CameraInfo + { + public int CameraNumber { get; set; } + public string Name { get; set; } + public int SourceId { get; set; } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index ca98c1fc..6db3c2e3 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -558,9 +558,41 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } } - public class SendingMode + public class SendingMode : ValueProperty { - public string Value { get; set; } + string _Value; + + /// + /// Sets Value and triggers the action when set + /// + public string Value + { + get + { + return _Value; + } + set + { + _Value = value; + OnValueChanged(); + } + } + + public bool LocalOnly + { + get + { + return _Value.ToLower() == "localonly"; + } + } + + public bool LocalRemote + { + get + { + return _Value.ToLower() == "localremote"; + } + } } public class LocalInstance @@ -573,6 +605,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public LocalInstance() { Source = new Source2(); + SendingMode = new SendingMode(); } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 5771d868..b87e47f6 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -982,18 +982,22 @@ ScreenIndexIsPinnedTo: {8} (a{17}) //End All calls trilist.SetSigFalseAction(joinMap.EndAllCalls.JoinNumber, EndAllCalls); - //End a specific call, specified by index - trilist.SetUShortSigAction(joinMap.EndCall.JoinNumber, (i) => - { - if (i > 0 && i <= 8) + //End a specific call, specified by index. Maximum 8 calls supported + for (int i = 0; i < joinMap.EndCallStart.JoinSpan; i++) + { + trilist.SetSigFalseAction((uint)(joinMap.EndCallStart.JoinNumber + i), () => { - var call = ActiveCalls[i - 1]; + var call = ActiveCalls[i]; if (call != null) { EndCall(call); } - } - }); + else + { + Debug.Console(0, this, "[End Call] Unable to find call at index '{0}'", i); + } + }); + } trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); @@ -1015,6 +1019,61 @@ ScreenIndexIsPinnedTo: {8} (a{17}) trilist.SetUshort(joinMap.ConnectedCallCount.JoinNumber, (ushort)ActiveCalls.Count); }; + + var joinCodec = this as IJoinCalls; + if (joinCodec != null) + { + trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls()); + + for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++) + { + trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () => + { + var call = ActiveCalls[i]; + if (call != null) + { + joinCodec.JoinCall(call); + } + else + { + Debug.Console(0, this, "[Join Call] Unable to find call at index '{0}'", i); + } + }); + } + } + + var holdCodec = this as IHasCallHold; + if (holdCodec != null) + { + for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++) + { + trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + i), () => + { + var call = ActiveCalls[i]; + if (call != null) + { + holdCodec.HoldCall(call); + } + else + { + Debug.Console(0, this, "[Hold Call] Unable to find call at index '{0}'", i); + } + }); + + trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + i), () => + { + var call = ActiveCalls[i]; + if (call != null) + { + holdCodec.ResumeCall(call); + } + else + { + Debug.Console(0, this, "[Resume Call] Unable to find call at index '{0}'", i); + } + }); + } + } } private string UpdateCallStatusXSig() @@ -1296,18 +1355,47 @@ ScreenIndexIsPinnedTo: {8} (a{17}) camera.TriggerAutoFocus(); }); + // Camera count + trilist.SetUshort(joinMap.CameraCount.JoinNumber, (ushort)codec.Cameras.Count); + + // Camera names + for (uint i = 0; i < joinMap.CameraNamesFb.JoinSpan; i++) + { + if (codec.Cameras[(int)i] != null) + { + trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, codec.Cameras[(int)i].Name); + } + else + { + trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, ""); + } + } + //Camera Select trilist.SetUShortSigAction(joinMap.CameraNumberSelect.JoinNumber, (i) => { - if (codec.SelectedCamera == null) return; - - codec.SelectCamera(codec.Cameras[i].Key); + if (i > 0 && i <= codec.Cameras.Count) + { + codec.SelectCamera(codec.Cameras[i - 1].Key); + } + else + { + Debug.Console(0, this, "Unable to select. No camera found at index {0}", i); + } }); + // Set initial selected camera feedback + if (codec.SelectedCamera != null) + { + trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)codec.Cameras.FindIndex((c) => c.Key == codec.SelectedCamera.Key)); + } + codec.CameraSelected += (sender, args) => { var i = (ushort)codec.Cameras.FindIndex((c) => c.Key == args.SelectedCamera.Key); + trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)(i + 1)); + if (codec is IHasCodecRoomPresets) { return; From d8aef1a0dad0211611a4b48630a054b15918d7a9 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 12 Nov 2021 22:07:11 -0700 Subject: [PATCH 006/202] feat(essentials): #865 More updates Adds ability to disable auto dialing behavior of selected directory contact. Adds XSig to send contact method info across bridge Adds XSig to send call history data across bridge and also joins to manipulate --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 125 +++++++++++++ .../Codec/iHasCallHistory.cs | 6 +- .../VideoCodec/VideoCodecBase.cs | 172 ++++++++++++++++-- 3 files changed, 287 insertions(+), 16 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index a0729352..a32dcc88 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -496,6 +496,19 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("DirectoryDisableAutoDialSelectedLine")] + public JoinDataComplete DirectoryDisableAutoDialSelectedLine = new JoinDataComplete( + new JoinData + { + JoinNumber = 107, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Set high to disable automatic dialing of a contact when selected", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); [JoinName("CameraTiltUp")] public JoinDataComplete CameraTiltUp = new JoinDataComplete( @@ -903,6 +916,20 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("RemoveSelectedRecentCallItem")] + public JoinDataComplete RemoveSelectedRecentCallItem = new JoinDataComplete( + new JoinData + { + JoinNumber = 181, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Removes the selected recent call item", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("SourceShareStart")] public JoinDataComplete SourceShareStart = new JoinDataComplete( new JoinData @@ -1219,6 +1246,34 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Analog }); + [JoinName("SelectRecentCallItem")] + public JoinDataComplete SelectRecentCallItem = new JoinDataComplete( + new JoinData + { + JoinNumber = 180, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Select/FB for Recent Call Item. Valid values 1 - 10", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("RecentCallOccurrenceType")] + public JoinDataComplete RecentCallOccurrenceType = new JoinDataComplete( + new JoinData + { + JoinNumber = 181, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Recent Call Occurrence Type. [0-3] 0 = Unknown, 1 = Placed, 2 = Received, 3 = NoAnswer", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + #endregion @@ -1352,6 +1407,20 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); + [JoinName("ContactMethods")] + public JoinDataComplete ContactMethods = new JoinDataComplete( + new JoinData + { + JoinNumber = 103, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Contact Methods - XSig, 10 entries", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + [JoinName("CameraPresetNames")] public JoinDataComplete CameraPresetNames = new JoinDataComplete( new JoinData @@ -1408,6 +1477,62 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); + [JoinName("SelectedRecentCallName")] + public JoinDataComplete SelectedRecentCallName = new JoinDataComplete( + new JoinData + { + JoinNumber = 171, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Recent Call Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelectedRecentCallNumber")] + public JoinDataComplete SelectedRecentCallNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 172, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Recent Call Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("RecentCallNamesStart")] + public JoinDataComplete RecentCallNamesStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 181, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Recent Call Names", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("RecentCallTimesStart")] + public JoinDataComplete RecentCallTimesStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 191, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Recent Calls Times", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + [JoinName("CurrentSource")] public JoinDataComplete CurrentSource = new JoinDataComplete( new JoinData diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasCallHistory.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasCallHistory.cs index 256938d1..83a74022 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasCallHistory.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasCallHistory.cs @@ -23,9 +23,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec public enum eCodecOccurrenceType { Unknown = 0, - Placed, - Received, - NoAnswer + Placed = 1, + Received = 2, + NoAnswer = 3, } /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index b87e47f6..114c1cf7 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -390,6 +390,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecPhoneToApi(codec as IHasPhoneDialing, trilist, joinMap); } + if (codec is IHasCallHistory) + { + LinkVideoCodecCallHistoryToApi(codec as IHasCallHistory, trilist, joinMap); + } + trilist.OnlineStatusChange += (device, args) => { if (!args.DeviceOnLine) return; @@ -436,6 +441,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec (codec as IHasPhoneDialing).PhoneOffHookFeedback.FireUpdate(); } + if (codec is IHasCallHistory) + { + UpdateCallHistory((codec as IHasCallHistory), trilist, joinMap); + } + SharingContentIsOnFeedback.FireUpdate(); trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); @@ -901,7 +911,9 @@ ScreenIndexIsPinnedTo: {8} (a{17}) trilist.SetStringSigAction(joinMap.DirectorySearchString.JoinNumber, codec.SearchDirectory); - trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i)); + trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i, trilist, joinMap)); + + // Report feedback for number of contact methods for selected contact trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot); @@ -921,7 +933,7 @@ ScreenIndexIsPinnedTo: {8} (a{17}) }; } - private void SelectDirectoryEntry(IHasDirectory codec, ushort i) + private void SelectDirectoryEntry(IHasDirectory codec, ushort i, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { var entry = codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1]; @@ -931,21 +943,87 @@ ScreenIndexIsPinnedTo: {8} (a{17}) return; } - var dialableEntry = entry as IInvitableContact; + // Allow auto dial of selected line + if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber)) + { + var dialableEntry = entry as IInvitableContact; - if (dialableEntry != null) - { - Dial(dialableEntry); - return; - } + if (dialableEntry != null) + { + Dial(dialableEntry); + return; + } - var entryToDial = entry as DirectoryContact; + var entryToDial = entry as DirectoryContact; - if (entryToDial == null) return; + if (entryToDial == null) return; + + Dial(entryToDial.ContactMethods[0].Number); + return; + } + else + { + // If auto dial is disabled... + var entryToDial = entry as DirectoryContact; + + if (entryToDial == null) return; + + trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedLine.JoinNumber, () => Dial(entryToDial.ContactMethods[0].Number)); + + var clearBytes = XSigHelpers.ClearOutputs(); + + trilist.SetString(joinMap.ContactMethods.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + var contactMethodsXSig = UpdateContactMethodsXSig(entryToDial); + + trilist.SetString(joinMap.ContactMethods.JoinNumber, contactMethodsXSig); + } - Dial(entryToDial.ContactMethods[0].Number); } + /// + /// Generates the XSig data representing the available contact methods for the selected DirectoryContact + /// + /// + /// + private string UpdateContactMethodsXSig(DirectoryContact contact) + { + const int maxMethods = 10; + const int maxStrings = 3; + const int offset = maxStrings; + var stringIndex = 0; + var arrayIndex = 0; + var tokenArray = new XSigToken[contact.ContactMethods.Count]; + + // TODO: Add code to generate XSig data + + foreach (var method in contact.ContactMethods) + { + if (arrayIndex >= maxMethods * offset) + break; + + //serials + tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, method.Number); + tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, method.ContactMethodId.ToString()); + tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, method.Device.ToString()); + + arrayIndex += offset; + stringIndex += maxStrings; + } + + while (arrayIndex < maxMethods) + { + tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty); + tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty); + tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty); + + arrayIndex += offset; + stringIndex += maxStrings; + } + + return GetXSigString(tokenArray); + } + private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot) { var contactIndex = 1; @@ -1079,7 +1157,7 @@ ScreenIndexIsPinnedTo: {8} (a{17}) private string UpdateCallStatusXSig() { const int maxCalls = 8; - const int maxStrings = 5; + const int maxStrings = 6; const int offset = 6; var stringIndex = 0; var digitalIndex = maxStrings * maxCalls; @@ -1457,7 +1535,75 @@ ScreenIndexIsPinnedTo: {8} (a{17}) }); } - private string SetCameraPresetNames(IEnumerable presets) + // Following fields only used for Bridging + private int _selectedRecentCallItemIndex; + private CodecCallHistory.CallHistoryEntry _selectedRecentCallItem; + + private void LinkVideoCodecCallHistoryToApi(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + codec.CallHistory.RecentCallsListHasChanged += (o, a) => + { + UpdateCallHistory(codec, trilist, joinMap); + }; + + // Selected item action and feedback + trilist.SetUShortSigAction(joinMap.SelectRecentCallItem.JoinNumber, (u) => + { + _selectedRecentCallItemIndex = (int)(u - 1); + trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, u); + + var _selectedRecentCallItem = codec.CallHistory.RecentCalls[_selectedRecentCallItemIndex]; + + if (_selectedRecentCallItem != null) + { + trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, _selectedRecentCallItem.Name); + trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, _selectedRecentCallItem.Number); + trilist.SetSigFalseAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber, () => codec.RemoveCallHistoryEntry(_selectedRecentCallItem)); + } + else + { + trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty); + trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty); + trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); + } + }); + } + + + + private void UpdateCallHistory(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + // Clear out selected item + _selectedRecentCallItemIndex = 0; + _selectedRecentCallItem = null; + trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, 0); + trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty); + trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty); + trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); + // + + + // Update the call history joins + var maxItems = joinMap.RecentCallNamesStart.JoinSpan; + + uint i = 0; + foreach(var item in codec.CallHistory.RecentCalls) + { + trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, item.Name); + trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, item.StartTime.ToShortTimeString()); + trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)item.OccurrenceType); + i++; + } + + for (uint index = i; i < maxItems; index++) + { + trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + index, string.Empty); + trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + index, string.Empty); + trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + index, 0); + } + } + + private string SetCameraPresetNames(IEnumerable presets) { return SetCameraPresetNames(presets.Select(p => p.Description).ToList()); } From cdafaf1bcbc8b8ce4bf531a6f7f9c2a0abb62831 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 17 Nov 2021 11:37:29 -0700 Subject: [PATCH 007/202] fix(essentials): Adds missing constructor for Configuration RootObject --- .../VideoCodec/CiscoCodec/xConfiguration.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs index e6ee8e4d..86e700b9 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs @@ -1843,6 +1843,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public class RootObject { public Configuration Configuration { get; set; } + + public RootObject() + { + Configuration = new Configuration(); + } } } } \ No newline at end of file From c685608f6747f580aca97f7f422813a9d8069f79 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 17 Nov 2021 12:24:58 -0700 Subject: [PATCH 008/202] fix(essentials): reworks logic for setting up cameras to wait until codec communication sync has finished --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 17 ++++++++++++----- .../VideoCodec/VideoCodecBase.cs | 13 +++++++++---- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 4c842f22..bce9d153 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -32,6 +32,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco IHasExternalSourceSwitching, IHasBranding, IHasCameraOff, IHasCameraMute, IHasDoNotDisturbMode, IHasHalfWakeMode, IHasCallHold, IJoinCalls { + private CiscoSparkCodecPropertiesConfig _config; + private bool _externalSourceChangeRequested; public event EventHandler DirectoryResultReturned; @@ -314,6 +316,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { var props = JsonConvert.DeserializeObject(config.Properties.ToString()); + _config = props; + // Use the configured phonebook results limit if present if (props.PhonebookResultsLimit > 0) { @@ -417,9 +421,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco InputPorts.Add(HdmiIn2); InputPorts.Add(HdmiIn3); OutputPorts.Add(HdmiOut1); - - SetUpCameras(props.CameraInfo); - CreateOsdSource(); ExternalSourceListEnabled = props.ExternalSourceListEnabled; @@ -638,6 +639,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// void SyncState_InitialSyncCompleted(object sender, EventArgs e) { + SetUpCameras(_config.CameraInfo); + // Fire the ready event SetIsReady(); //CommDebuggingIsOn = false; @@ -1912,9 +1915,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { var internalCamera = new CiscoSparkCamera(Key + "-camera1", "Near End", this, 1); - if (CodecStatus.Status.Cameras.Camera[0] != null && CodecStatus.Status.Cameras.Camera[0].Capabilities != null) + if (camCount > 0) { - internalCamera.SetCapabilites(CodecStatus.Status.Cameras.Camera[0].Capabilities.Options.Value); + // Try to get the capabilities from the codec + if (CodecStatus.Status.Cameras.Camera[0] != null && CodecStatus.Status.Cameras.Camera[0].Capabilities != null) + { + internalCamera.SetCapabilites(CodecStatus.Status.Cameras.Camera[0].Capabilities.Options.Value); + } } Cameras.Add(internalCamera); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 114c1cf7..789723d7 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -328,15 +328,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecVolumeToApi(trilist, joinMap); + // Register for this event to link any functions that require the codec to be ready first + codec.IsReadyChange += (o, a) => + { + if (codec is IHasCodecCameras) + { + LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap); + } + }; + if (codec is ICommunicationMonitor) { LinkVideoCodecCommMonitorToApi(codec as ICommunicationMonitor, trilist, joinMap); } - if (codec is IHasCodecCameras) - { - LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap); - } if (codec is IHasCodecSelfView) { From 4552a15cbb2acf6df52158aaf2eccfe4965b0990 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 7 Dec 2021 16:22:15 -0700 Subject: [PATCH 009/202] fix(essentials): #865 Updates to join map and bridging based on feedback from testing --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 164 ++++++++++++++---- .../CiscoCodec/CiscoCodecJoinMap.cs | 31 +++- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 4 + .../VideoCodec/VideoCodecBase.cs | 29 +++- 4 files changed, 186 insertions(+), 42 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index a32dcc88..08281109 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -34,7 +34,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("1")] + [JoinName("Dtmf1")] public JoinDataComplete Dtmf1 = new JoinDataComplete( new JoinData { @@ -48,7 +48,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("2")] + [JoinName("Dtmf2")] public JoinDataComplete Dtmf2 = new JoinDataComplete( new JoinData { @@ -62,7 +62,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("3")] + [JoinName("Dtmf3")] public JoinDataComplete Dtmf3 = new JoinDataComplete( new JoinData { @@ -76,7 +76,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("4")] + [JoinName("Dtmf4")] public JoinDataComplete Dtmf4 = new JoinDataComplete( new JoinData { @@ -90,7 +90,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("5")] + [JoinName("Dtmf5")] public JoinDataComplete Dtmf5 = new JoinDataComplete( new JoinData { @@ -104,7 +104,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("6")] + [JoinName("Dtmf6")] public JoinDataComplete Dtmf6 = new JoinDataComplete( new JoinData { @@ -118,7 +118,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("7")] + [JoinName("Dtmf7")] public JoinDataComplete Dtmf7 = new JoinDataComplete( new JoinData { @@ -132,7 +132,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("8")] + [JoinName("Dtmf8")] public JoinDataComplete Dtmf8 = new JoinDataComplete( new JoinData { @@ -146,7 +146,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("9")] + [JoinName("Dtmf9")] public JoinDataComplete Dtmf9 = new JoinDataComplete( new JoinData { @@ -160,7 +160,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("0")] + [JoinName("Dtmf0")] public JoinDataComplete Dtmf0 = new JoinDataComplete( new JoinData { @@ -174,7 +174,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("*")] + [JoinName("DtmfStar")] public JoinDataComplete DtmfStar = new JoinDataComplete( new JoinData { @@ -188,7 +188,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("#")] + [JoinName("DtmfPound")] public JoinDataComplete DtmfPound = new JoinDataComplete( new JoinData { @@ -295,12 +295,12 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Dial manual string", + Description = "Dial manual string specified by CurrentDialString serial join", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DialPhoneCall")] + [JoinName("DialPhone")] public JoinDataComplete DialPhone = new JoinDataComplete( new JoinData { @@ -328,7 +328,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("EndPhoneCall")] + [JoinName("HangUpPhone")] public JoinDataComplete HangUpPhone = new JoinDataComplete( new JoinData { @@ -337,7 +337,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Hang Up PHone", + Description = "Hang Up Phone", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); @@ -361,11 +361,11 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps new JoinData { JoinNumber = 90, - JoinSpan = 8 + JoinSpan = 1 }, new JoinMetadata { - Description = "End a specific call by call index. ", + Description = "Join all calls", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); @@ -379,7 +379,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "End a specific call by call index. ", + Description = "Join a specific call by call index. ", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); @@ -645,7 +645,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Pulse to save selected preset. FB will pulse for 3s when preset saved.", + Description = "Pulse to save selected preset spcified by CameraPresetSelect analog join. FB will pulse for 3s when preset saved.", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); @@ -659,7 +659,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Camera Mode Auto", + Description = "Camera Mode Auto. Enables camera auto tracking mode, with feedback", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); @@ -673,7 +673,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Camera Mode Manual", + Description = "Camera Mode Manual. Disables camera auto tracking mode, with feedback", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); @@ -687,7 +687,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Camera Mode Off", + Description = "Camera Mode Off. Disables camera video, with feedback. Works like video mute.", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); @@ -925,7 +925,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Removes the selected recent call item", + Description = "Removes the selected recent call item specified by the SelectRecentCallItem analog join", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); @@ -995,7 +995,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "advance selfview position", + Description = "Toggles selfview position", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); @@ -1010,7 +1010,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps new JoinMetadata { Description = "Holds Call at specified index", - JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); @@ -1028,6 +1028,34 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("MultiSiteOptionIsEnabled")] + public JoinDataComplete MultiSiteOptionIsEnabled = new JoinDataComplete( + new JoinData + { + JoinNumber = 301, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Multi site option is enabled FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("AutoAnswerEnabled")] + public JoinDataComplete AutoAnswerEnabled = new JoinDataComplete( + new JoinData + { + JoinNumber = 302, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Auto Answer is enabled FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("ParticipantAudioMuteToggleStart")] public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( new JoinData @@ -1289,12 +1317,12 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Current Dial String", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + Description = "Value to dial when ManualDial digital join is pulsed", + JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("PhoneString")] + [JoinName("PhoneDialString")] public JoinDataComplete PhoneDialString = new JoinDataComplete( new JoinData { @@ -1308,7 +1336,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); - [JoinName("CurrentCallName")] + [JoinName("CurrentCallData")] public JoinDataComplete CurrentCallData = new JoinDataComplete( new JoinData { @@ -1435,8 +1463,8 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); - [JoinName("CameraLayoutStringFb")] - public JoinDataComplete CameraLayoutStringFb = new JoinDataComplete( + [JoinName("CurrentLayoutStringFb")] + public JoinDataComplete CurrentLayoutStringFb = new JoinDataComplete( new JoinData { JoinNumber = 141, @@ -1559,7 +1587,77 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps Description = "advance selfview position", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial - }); + }); + + [JoinName("DeviceIpAddresss")] + public JoinDataComplete DeviceIpAddresss = new JoinDataComplete( + new JoinData + { + JoinNumber = 301, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "IP Address of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SipPhoneNumber")] + public JoinDataComplete SipPhoneNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 302, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "SIP phone number of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("E164Alias")] + public JoinDataComplete E164Alias = new JoinDataComplete( + new JoinData + { + JoinNumber = 303, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "E164 alias of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("H323Id")] + public JoinDataComplete H323Id = new JoinDataComplete( + new JoinData + { + JoinNumber = 304, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "H323 ID of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SipUri")] + public JoinDataComplete SipUri = new JoinDataComplete( + new JoinData + { + JoinNumber = 305, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "SIP URI of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); [JoinName("DirectoryEntrySelectedName")] public JoinDataComplete DirectoryEntrySelectedName = new JoinDataComplete( diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecJoinMap.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecJoinMap.cs index 44256ca4..2396afdc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecJoinMap.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecJoinMap.cs @@ -32,7 +32,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco }, new JoinMetadata { - Description = "Presentation Local Only Feedback", + Description = "Presentation Local and Remote Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); @@ -41,7 +41,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public JoinDataComplete ActivateDoNotDisturbMode = new JoinDataComplete( new JoinData { - JoinNumber = 221, + JoinNumber = 241, JoinSpan = 1 }, new JoinMetadata @@ -55,7 +55,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public JoinDataComplete DeactivateDoNotDisturbMode = new JoinDataComplete( new JoinData { - JoinNumber = 222, + JoinNumber = 242, JoinSpan = 1 }, new JoinMetadata @@ -69,7 +69,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public JoinDataComplete ToggleDoNotDisturbMode = new JoinDataComplete( new JoinData { - JoinNumber = 223, + JoinNumber = 243, JoinSpan = 1 }, new JoinMetadata @@ -83,7 +83,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public JoinDataComplete ActivateStandby = new JoinDataComplete( new JoinData { - JoinNumber = 226, + JoinNumber = 246, JoinSpan = 1 }, new JoinMetadata @@ -97,7 +97,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public JoinDataComplete DeactivateStandby = new JoinDataComplete( new JoinData { - JoinNumber = 227, + JoinNumber = 247, JoinSpan = 1 }, new JoinMetadata @@ -111,7 +111,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public JoinDataComplete ActivateHalfWakeMode = new JoinDataComplete( new JoinData { - JoinNumber = 228, + JoinNumber = 248, JoinSpan = 1 }, new JoinMetadata @@ -125,7 +125,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public JoinDataComplete EnteringStandbyMode = new JoinDataComplete( new JoinData { - JoinNumber = 229, + JoinNumber = 249, JoinSpan = 1 }, new JoinMetadata @@ -174,6 +174,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco #region Serials + [JoinName("CommandToDevice")] + public JoinDataComplete CommandToDevice = new JoinDataComplete( + new JoinData + { + JoinNumber = 5, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Sends a serial command to the device. Do not include the delimiter, it will be added automatically.", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + #endregion diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index bce9d153..3ed2dae1 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -1662,6 +1662,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public void LinkCiscoCodecToApi(BasicTriList trilist, CiscoCodecJoinMap joinMap) { + // Custom commands to codec + trilist.SetStringSigAction(joinMap.CommandToDevice.JoinNumber, (s) => this.SendText(s)); + + var dndCodec = this as IHasDoNotDisturbMode; if (dndCodec != null) { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 789723d7..45fc67ee 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -328,6 +328,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecVolumeToApi(trilist, joinMap); + LinkVideoCodecInfoToApi(trilist, joinMap); + // Register for this event to link any functions that require the codec to be ready first codec.IsReadyChange += (o, a) => { @@ -459,6 +461,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec }; } + private void LinkVideoCodecInfoToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled); + trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled); + trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress); + trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber); + trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias); + trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id); + trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri); + + trilist.OnlineStatusChange += (o, a) => + { + if (a.DeviceOnLine) + { + trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled); + trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled); + trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress); + trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber); + trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias); + trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id); + trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri); + } + }; + } + private void LinkVideoCodecPhoneToApi(IHasPhoneDialing codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { codec.PhoneOffHookFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PhoneHookState.JoinNumber]); @@ -1274,7 +1301,7 @@ ScreenIndexIsPinnedTo: {8} (a{17}) { trilist.SetSigFalseAction(joinMap.CameraLayout.JoinNumber, codec.LocalLayoutToggle); - codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.CameraLayoutStringFb.JoinNumber]); + codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentLayoutStringFb.JoinNumber]); } private void LinkVideoCodecCameraModeToApi(IHasCameraAutoMode codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) From 90e22e9136f96c4d8eec05ee5ae4292ea83310ab Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 7 Dec 2021 16:45:14 -0700 Subject: [PATCH 010/202] fix(essentials): #865 Adds SelectedContactMethodCount join to report the number of methods for the selected contact --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 14 ++++++++++++++ .../VideoCodec/VideoCodecBase.cs | 9 ++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 08281109..205c4e09 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -1204,6 +1204,20 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Analog }); + [JoinName("SelectedContactMethodCount")] + public JoinDataComplete SelectedContactMethodCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 102, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the number of contact methods for the selected contact", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + [JoinName("CameraPresetSelect")] public JoinDataComplete CameraPresetSelect = new JoinDataComplete( new JoinData diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 45fc67ee..9714d04c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -972,6 +972,7 @@ ScreenIndexIsPinnedTo: {8} (a{17}) if (entry is DirectoryFolder) { codec.GetDirectoryFolderContents(entry.FolderId); + trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0); return; } @@ -998,10 +999,16 @@ ScreenIndexIsPinnedTo: {8} (a{17}) // If auto dial is disabled... var entryToDial = entry as DirectoryContact; - if (entryToDial == null) return; + if (entryToDial == null) + { + trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0); + return; + } trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedLine.JoinNumber, () => Dial(entryToDial.ContactMethods[0].Number)); + trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, (ushort)entryToDial.ContactMethods.Count); + var clearBytes = XSigHelpers.ClearOutputs(); trilist.SetString(joinMap.ContactMethods.JoinNumber, From 611f0bec2eff7a243dfac02e98b63797944da508 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 7 Dec 2021 19:40:03 -0700 Subject: [PATCH 011/202] fix(essentials): #865 Adds DialselectedRecentCallItem join --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 16 +++++++++++++++- .../VideoCodec/VideoCodecBase.cs | 2 ++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 205c4e09..862e1b2a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -925,7 +925,21 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Removes the selected recent call item specified by the SelectRecentCallItem analog join", + Description = "Pulse to remove the selected recent call item specified by the SelectRecentCallItem analog join", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialSelectedRecentCallItem")] + public JoinDataComplete DialSelectedRecentCallItem = new JoinDataComplete( + new JoinData + { + JoinNumber = 182, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to dial the selected recent call item specified by the SelectRecentCallItem analog join", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 9714d04c..51376b51 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1598,12 +1598,14 @@ ScreenIndexIsPinnedTo: {8} (a{17}) trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, _selectedRecentCallItem.Name); trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, _selectedRecentCallItem.Number); trilist.SetSigFalseAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber, () => codec.RemoveCallHistoryEntry(_selectedRecentCallItem)); + trilist.SetSigFalseAction(joinMap.DialSelectedRecentCallItem.JoinNumber, () => this.Dial(_selectedRecentCallItem.Number)); } else { trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty); trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty); trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DialSelectedRecentCallItem.JoinNumber); } }); } From abdd1b38f8c6a57773c264e8bc0f36056a525a5d Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 2 Feb 2022 09:22:13 -0700 Subject: [PATCH 012/202] feat (Core): #898 Add name to `GenericQueue` Thread This name will show up in console using the `SSPTASKS` command and allow for easier troubleshooting. --- .../PepperDashEssentialsBase/Queues/GenericQueue.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs index a1cef30d..f6b0794c 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs @@ -139,7 +139,8 @@ namespace PepperDash.Essentials.Core.Queues _queue = new CrestronQueue(cap); _worker = new Thread(ProcessQueue, null, Thread.eThreadStartOptions.Running) { - Priority = priority + Priority = priority, + Name = _key }; SetDelayValues(pacing); From 742ff4bc1b7ff5633f0e0f2ac18f1744ae2f36ed Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 2 Feb 2022 10:18:04 -0700 Subject: [PATCH 013/202] fix(essentials): Updates config type for Vtc1 type rooms --- .../Room/Types/EssentialsCombinedHuddleVtc1Room.cs | 6 +++--- PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs | 2 +- .../Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs index 9dec21f2..50186d0b 100644 --- a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs @@ -89,7 +89,7 @@ namespace PepperDash.Essentials } } - public EssentialsConferenceRoomPropertiesConfig PropertiesConfig { get; private set; } + public EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; private set; } private List Displays; @@ -199,7 +199,7 @@ namespace PepperDash.Essentials { try { - PropertiesConfig = JsonConvert.DeserializeObject + PropertiesConfig = JsonConvert.DeserializeObject (config.Properties.ToString()); VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as @@ -361,7 +361,7 @@ namespace PepperDash.Essentials protected override void CustomSetConfig(DeviceConfig config) { - var newPropertiesConfig = JsonConvert.DeserializeObject(config.Properties.ToString()); + var newPropertiesConfig = JsonConvert.DeserializeObject(config.Properties.ToString()); if (newPropertiesConfig != null) PropertiesConfig = newPropertiesConfig; diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index f429b8c8..ba4567dc 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -101,7 +101,7 @@ namespace PepperDash.Essentials } } - public EssentialsConferenceRoomPropertiesConfig PropertiesConfig { get; private set; } + public EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; private set; } public IRoutingSinkWithSwitching DefaultDisplay { get; private set; } public IBasicVolumeControls DefaultAudioDevice { get; private set; } diff --git a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs index 4b13145c..03f7340b 100644 --- a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs @@ -10,7 +10,7 @@ namespace PepperDash.Essentials public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange, IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback { - EssentialsConferenceRoomPropertiesConfig PropertiesConfig { get; } + EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; } bool ExcludeFromGlobalFunctions { get; } From c6023ad7005071121e1f1f965b28adb0add10aba Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 4 Feb 2022 15:51:29 -0700 Subject: [PATCH 014/202] fix(essentials): Adds missing help message property to tech room config and exposes config --- .../Room/Config/EssentialsTechRoomConfig.cs | 3 ++ .../Room/Types/EssentialsTechRoom.cs | 42 +++++++++---------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/PepperDashEssentials/Room/Config/EssentialsTechRoomConfig.cs b/PepperDashEssentials/Room/Config/EssentialsTechRoomConfig.cs index 9ff3a2d2..2944b854 100644 --- a/PepperDashEssentials/Room/Config/EssentialsTechRoomConfig.cs +++ b/PepperDashEssentials/Room/Config/EssentialsTechRoomConfig.cs @@ -56,6 +56,9 @@ namespace PepperDash.Essentials.Room.Config [JsonProperty("mirroredTuners")] public Dictionary MirroredTuners { get; set; } + [JsonProperty("helpMessage")] + public string HelpMessage { get; set; } + /// /// Indicates the room /// diff --git a/PepperDashEssentials/Room/Types/EssentialsTechRoom.cs b/PepperDashEssentials/Room/Types/EssentialsTechRoom.cs index c2b08f89..b97ef9c4 100644 --- a/PepperDashEssentials/Room/Types/EssentialsTechRoom.cs +++ b/PepperDashEssentials/Room/Types/EssentialsTechRoom.cs @@ -19,7 +19,7 @@ namespace PepperDash.Essentials { public class EssentialsTechRoom : EssentialsRoomBase, ITvPresetsProvider, IBridgeAdvanced, IRunDirectRouteAction { - private readonly EssentialsTechRoomConfig _config; + public EssentialsTechRoomConfig PropertiesConfig { get; private set; } private readonly Dictionary _displays; private readonly DevicePresetsModel _tunerPresets; @@ -57,16 +57,16 @@ namespace PepperDash.Essentials public EssentialsTechRoom(DeviceConfig config) : base(config) { - _config = config.Properties.ToObject(); + PropertiesConfig = config.Properties.ToObject(); - _tunerPresets = new DevicePresetsModel(String.Format("{0}-presets", config.Key), _config.PresetsFileName); + _tunerPresets = new DevicePresetsModel(String.Format("{0}-presets", config.Key), PropertiesConfig.PresetsFileName); - _tunerPresets.SetFileName(_config.PresetsFileName); + _tunerPresets.SetFileName(PropertiesConfig.PresetsFileName); _tunerPresets.PresetRecalled += TunerPresetsOnPresetRecalled; - _tuners = GetDevices(_config.Tuners); - _displays = GetDevices(_config.Displays); + _tuners = GetDevices(PropertiesConfig.Tuners); + _displays = GetDevices(PropertiesConfig.Displays); RoomPowerIsOnFeedback = new BoolFeedback(() => RoomPowerIsOn); @@ -153,7 +153,7 @@ namespace PepperDash.Essentials private void CreateOrUpdateScheduledEvents() { - var eventsConfig = _config.ScheduledEvents; + var eventsConfig = PropertiesConfig.ScheduledEvents; GetOrCreateScheduleGroup(); @@ -207,21 +207,21 @@ namespace PepperDash.Essentials { //update config based on key of scheduleEvent GetOrCreateScheduleGroup(); - var existingEventIndex = _config.ScheduledEvents.FindIndex((e) => e.Key == scheduledEvent.Key); + var existingEventIndex = PropertiesConfig.ScheduledEvents.FindIndex((e) => e.Key == scheduledEvent.Key); if (existingEventIndex < 0) { - _config.ScheduledEvents.Add(scheduledEvent); + PropertiesConfig.ScheduledEvents.Add(scheduledEvent); } else { - _config.ScheduledEvents[existingEventIndex] = scheduledEvent; + PropertiesConfig.ScheduledEvents[existingEventIndex] = scheduledEvent; } //create or update event based on config CreateOrUpdateSingleEvent(scheduledEvent); //save config - Config.Properties = JToken.FromObject(_config); + Config.Properties = JToken.FromObject(PropertiesConfig); CustomSetConfig(Config); //Fire Event @@ -230,7 +230,7 @@ namespace PepperDash.Essentials public List GetScheduledEvents() { - return _config.ScheduledEvents ?? new List(); + return PropertiesConfig.ScheduledEvents ?? new List(); } private void OnScheduledEventUpdate() @@ -242,14 +242,14 @@ namespace PepperDash.Essentials return; } - handler(this, new ScheduledEventEventArgs {ScheduledEvents = _config.ScheduledEvents}); + handler(this, new ScheduledEventEventArgs {ScheduledEvents = PropertiesConfig.ScheduledEvents}); } public event EventHandler ScheduledEventsChanged; private void HandleScheduledEvent(ScheduledEvent schevent, ScheduledEventCommon.eCallbackReason type) { - var eventConfig = _config.ScheduledEvents.FirstOrDefault(e => e.Key == schevent.Name); + var eventConfig = PropertiesConfig.ScheduledEvents.FirstOrDefault(e => e.Key == schevent.Name); if (eventConfig == null) { @@ -286,11 +286,11 @@ Params: {2}" { Debug.Console(2, this, "Room Powering On"); - var dummySource = DeviceManager.GetDeviceForKey(_config.DummySourceKey) as IRoutingOutputs; + var dummySource = DeviceManager.GetDeviceForKey(PropertiesConfig.DummySourceKey) as IRoutingOutputs; if (dummySource == null) { - Debug.Console(1, this, "Unable to get source with key: {0}", _config.DummySourceKey); + Debug.Console(1, this, "Unable to get source with key: {0}", PropertiesConfig.DummySourceKey); return; } @@ -376,12 +376,12 @@ Params: {2}" bridge.AddJoinMap(Key, joinMap); } - if (_config.IsPrimary) + if (PropertiesConfig.IsPrimary) { Debug.Console(1, this, "Linking Primary system Tuner Preset Mirroring"); - if (_config.MirroredTuners != null && _config.MirroredTuners.Count > 0) + if (PropertiesConfig.MirroredTuners != null && PropertiesConfig.MirroredTuners.Count > 0) { - foreach (var tuner in _config.MirroredTuners) + foreach (var tuner in PropertiesConfig.MirroredTuners) { var f = CurrentPresetsFeedbacks[tuner.Value]; @@ -423,9 +423,9 @@ Params: {2}" { Debug.Console(1, this, "Linking Secondary system Tuner Preset Mirroring"); - if (_config.MirroredTuners != null && _config.MirroredTuners.Count > 0) + if (PropertiesConfig.MirroredTuners != null && PropertiesConfig.MirroredTuners.Count > 0) { - foreach (var tuner in _config.MirroredTuners) + foreach (var tuner in PropertiesConfig.MirroredTuners) { var t = _tuners[tuner.Value]; From bc826c9e1712655cc8ef79e7c35243c234de1d42 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 4 Feb 2022 16:41:57 -0700 Subject: [PATCH 015/202] fix(essentials): updates action workflows to specify windows-2019 instead of latest --- .github/workflows/docker.yml | 2 +- .github/workflows/main.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 94c45937..cdcc925b 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -22,7 +22,7 @@ env: RELEASE_BRANCH: main jobs: Build_Project: - runs-on: windows-latest + runs-on: windows-2019 steps: # First we checkout the source repo - name: Checkout repo diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dc219ce3..ef43152b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,7 @@ env: RELEASE_BRANCH: main jobs: Build_Project: - runs-on: windows-latest + runs-on: windows-2019 steps: # First we checkout the source repo - name: Checkout repo From d9181c780fcfc77a8a9f99505454d1270a139a6e Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Mon, 7 Feb 2022 16:45:08 -0600 Subject: [PATCH 016/202] fix: Updated _receiveQueue capacity from 512 to 2048 to help with processing large amounts of push data received from zoom. --- .../Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 8fc40f29..5eba02ed 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -59,7 +59,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom _props = JsonConvert.DeserializeObject(config.Properties.ToString()); - _receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 512); + _receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 2048); Communication = comm; From 7b2498ac6b9f031e716592090e19f62960ab0298 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Mon, 7 Feb 2022 16:50:35 -0600 Subject: [PATCH 017/202] fix: added JSON property decorator to configuration properties. --- .../ZoomRoom/ZoomRoomPropertiesConfig.cs | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs index 4c9b08c2..3f752f43 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs @@ -2,30 +2,40 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using Crestron.SimplSharp; - +using Crestron.SimplSharp; +using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { public class ZoomRoomPropertiesConfig - { - public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; } - - public bool DisablePhonebookAutoDownload { get; set; } - public bool SupportsCameraAutoMode { get; set; } + { + [JsonProperty("communicationMonitorProperties")] + public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; } + + [JsonProperty("disablePhonebookAutoDownload")] + public bool DisablePhonebookAutoDownload { get; set; } + + [JsonProperty("supportsCameraAutoMode")] + public bool SupportsCameraAutoMode { get; set; } + + [JsonProperty("supportsCameraOff")] public bool SupportsCameraOff { get; set; } - //if true, the layouts will be set automatically when sharing starts/ends or a call is joined + //if true, the layouts will be set automatically when sharing starts/ends or a call is joined + [JsonProperty("autoDefaultLayouts")] public bool AutoDefaultLayouts { get; set; } - /* This layout will be selected when Sharing starts (either from Far end or locally)*/ + /* This layout will be selected when Sharing starts (either from Far end or locally)*/ + [JsonProperty("defaultSharingLayout")] public string DefaultSharingLayout { get; set; } - //This layout will be selected when a call is connected and no content is being shared - public string DefaultCallLayout { get; set; } - + //This layout will be selected when a call is connected and no content is being shared + [JsonProperty("defaultCallLayout")] + public string DefaultCallLayout { get; set; } + + [JsonProperty("minutesBeforeMeetingStart")] public int MinutesBeforeMeetingStart { get; set; } } } \ No newline at end of file From e19b0ba530b859fd16b1357ff800a3fb1b462ea6 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Mon, 7 Feb 2022 16:58:24 -0600 Subject: [PATCH 018/202] fix: updated yaml files to point to windows-2019 to resolve action failures. --- .github/workflows/docker.yml | 4 ++-- .github/workflows/main.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 94c45937..e654fa68 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -22,7 +22,7 @@ env: RELEASE_BRANCH: main jobs: Build_Project: - runs-on: windows-latest + runs-on: windows-2019 steps: # First we checkout the source repo - name: Checkout repo @@ -98,7 +98,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} Push_Nuget_Package: needs: Build_Project - runs-on: windows-latest + runs-on: windows-2019 steps: - name: Download Build Version Info uses: actions/download-artifact@v1 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dc219ce3..abcc8419 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,7 @@ env: RELEASE_BRANCH: main jobs: Build_Project: - runs-on: windows-latest + runs-on: windows-2019 steps: # First we checkout the source repo - name: Checkout repo @@ -82,7 +82,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} Push_Nuget_Package: needs: Build_Project - runs-on: windows-latest + runs-on: windows-2019 steps: - name: Download Build Version Info uses: actions/download-artifact@v1 From 6cd1a03ee0a8ff925732210a00baed2662adfcb8 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 8 Feb 2022 09:38:40 -0600 Subject: [PATCH 019/202] fix: Updated LinkVideoCodecToApi trilist.onlinestatus change to fix CameraSupportsAudioMode passing true rather than property. --- .../Essentials Devices Common/VideoCodec/VideoCodecBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index cd70119f..438d6c56 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -411,7 +411,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (codec is IHasCameraAutoMode) { - trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, true); + trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, SupportsCameraAutoMode); (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); } From b5589364ff90afb4c26234a4015043c068c93545 Mon Sep 17 00:00:00 2001 From: Jonathan Arndt Date: Tue, 8 Feb 2022 12:15:29 -0800 Subject: [PATCH 020/202] Instantiate xConfiguration members of Configuration, AutoAnswer, and Conference classes --- .github/workflows/docker.yml | 4 ++-- .github/workflows/main.yml | 4 ++-- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 8 ++++++++ .../VideoCodec/CiscoCodec/xConfiguration.cs | 13 +++++++++++++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 94c45937..e654fa68 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -22,7 +22,7 @@ env: RELEASE_BRANCH: main jobs: Build_Project: - runs-on: windows-latest + runs-on: windows-2019 steps: # First we checkout the source repo - name: Checkout repo @@ -98,7 +98,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} Push_Nuget_Package: needs: Build_Project - runs-on: windows-latest + runs-on: windows-2019 steps: - name: Download Build Version Info uses: actions/download-artifact@v1 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dc219ce3..abcc8419 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,7 @@ env: RELEASE_BRANCH: main jobs: Build_Project: - runs-on: windows-latest + runs-on: windows-2019 steps: # First we checkout the source repo - name: Checkout repo @@ -82,7 +82,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} Push_Nuget_Package: needs: Build_Project - runs-on: windows-latest + runs-on: windows-2019 steps: - name: Download Build Version Info uses: actions/download-artifact@v1 diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 3ed2dae1..eee9a887 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -2154,6 +2154,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { get { + CrestronConsole.PrintLine("CiscoSparkCodec AutoAnswerEnabled << Get >>"); + if (CodecConfiguration == null) CrestronConsole.PrintLine("CiscoSparkCodec > CodecConfiguration == Null"); + if (CodecConfiguration.Configuration == null) CrestronConsole.PrintLine("CiscoSparkCodec > CodecConfiguration.Configuration == Null"); + if (CodecConfiguration.Configuration.Conference == null) CrestronConsole.PrintLine("CiscoSparkCodec > CodecConfiguration.Configuration.Conference == Null"); + if (CodecConfiguration.Configuration.Conference.AutoAnswer == null) CrestronConsole.PrintLine("CiscoSparkCodec > CodecConfiguration.Configuration.Conference.AutoAnswer == Null"); + if (CodecConfiguration.Configuration.Conference.AutoAnswer.Mode == null) CrestronConsole.PrintLine("CiscoSparkCodec > CodecConfiguration.Configuration.Conference.AutoAnswer.Mode == Null"); + if (CodecConfiguration.Configuration.Conference.AutoAnswer.Mode.Value == null) CrestronConsole.PrintLine("CiscoSparkCodec > CodecConfiguration.Configuration.Conference.AutoAnswer.Mode.Value == Null"); + if (CodecConfiguration.Configuration.Conference.AutoAnswer.Mode.Value.ToLower() == "on") return true; else diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs index 86e700b9..3a8c6252 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs @@ -376,6 +376,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public Delay Delay { get; set; } public Mode9 Mode { get; set; } public Mute2 Mute { get; set; } + + public AutoAnswer() + { + Mode = new Mode9(); + Delay = new Delay(); + Mute = new Mute2(); + } } public class Protocol @@ -476,6 +483,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public MaxTotalTransmitCallRate MaxTotalTransmitCallRate { get; set; } public MaxTransmitCallRate MaxTransmitCallRate { get; set; } public MultiStream MultiStream { get; set; } + + public Conference() + { + AutoAnswer = new AutoAnswer(); + } } public class LoginName @@ -1837,6 +1849,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public Configuration() { Audio = new Audio(); + Conference = new Conference(); } } From 64352811c5036d7c1e33536fd5adb8e0d2218d06 Mon Sep 17 00:00:00 2001 From: Jonathan Arndt Date: Tue, 8 Feb 2022 13:31:13 -0800 Subject: [PATCH 021/202] Update VideoCodecBase.LinkVideoCodecCameraToApi FOR loop checking camera names to first check camera count --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 14 ++------------ .../VideoCodec/VideoCodecBase.cs | 3 ++- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index eee9a887..c981c8f0 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -2154,18 +2154,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { get { - CrestronConsole.PrintLine("CiscoSparkCodec AutoAnswerEnabled << Get >>"); - if (CodecConfiguration == null) CrestronConsole.PrintLine("CiscoSparkCodec > CodecConfiguration == Null"); - if (CodecConfiguration.Configuration == null) CrestronConsole.PrintLine("CiscoSparkCodec > CodecConfiguration.Configuration == Null"); - if (CodecConfiguration.Configuration.Conference == null) CrestronConsole.PrintLine("CiscoSparkCodec > CodecConfiguration.Configuration.Conference == Null"); - if (CodecConfiguration.Configuration.Conference.AutoAnswer == null) CrestronConsole.PrintLine("CiscoSparkCodec > CodecConfiguration.Configuration.Conference.AutoAnswer == Null"); - if (CodecConfiguration.Configuration.Conference.AutoAnswer.Mode == null) CrestronConsole.PrintLine("CiscoSparkCodec > CodecConfiguration.Configuration.Conference.AutoAnswer.Mode == Null"); - if (CodecConfiguration.Configuration.Conference.AutoAnswer.Mode.Value == null) CrestronConsole.PrintLine("CiscoSparkCodec > CodecConfiguration.Configuration.Conference.AutoAnswer.Mode.Value == Null"); - - if (CodecConfiguration.Configuration.Conference.AutoAnswer.Mode.Value.ToLower() == "on") - return true; - else - return false; + if (CodecConfiguration.Configuration.Conference.AutoAnswer.Mode.Value == null) return false; + return CodecConfiguration.Configuration.Conference.AutoAnswer.Mode.Value.ToLower() == "on"; } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 51376b51..9860d1c3 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1478,7 +1478,8 @@ ScreenIndexIsPinnedTo: {8} (a{17}) // Camera names for (uint i = 0; i < joinMap.CameraNamesFb.JoinSpan; i++) { - if (codec.Cameras[(int)i] != null) + //Check the count first + if (i < codec.Cameras.Count && codec.Cameras[(int)i] != null) { trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, codec.Cameras[(int)i].Name); } From 93bfcc7baa708bef2407c74283e14bfff80d9ea5 Mon Sep 17 00:00:00 2001 From: Jonathan Arndt Date: Tue, 8 Feb 2022 16:24:54 -0800 Subject: [PATCH 022/202] Add logic to subscribe to PhoneBookSyncState during the CustomActivate method within CiscoSparkCodec class --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 2 +- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 8 +++ .../VideoCodec/VideoCodecBase.cs | 64 +++++++++++++++---- 3 files changed, 59 insertions(+), 15 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 862e1b2a..368a547f 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -464,7 +464,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps new JoinMetadata { Description = "Go to Directory Root", - JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index c981c8f0..efe1914d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -590,9 +590,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco CrestronConsole.AddNewConsoleCommand(GetPhonebook, "GetCodecPhonebook", "Triggers a refresh of the codec phonebook", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(GetBookings, "GetCodecBookings", "Triggers a refresh of the booking data for today", ConsoleAccessLevelEnum.AccessOperator); + PhonebookSyncState.InitialSyncCompleted += new EventHandler(PhonebookSyncState_InitialSyncCompleted); + return base.CustomActivate(); } + void PhonebookSyncState_InitialSyncCompleted(object sender, EventArgs e) + { + OnDirectoryResultReturned(DirectoryRoot); + } + #region Overrides of Device public override void Initialize() @@ -1144,6 +1151,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco var handler = DirectoryResultReturned; if (handler != null) { + Debug.Console(2, this, "Directory result returned"); handler(this, new DirectoryEventArgs() { Directory = result, diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 9860d1c3..f60ece74 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -937,9 +937,7 @@ ScreenIndexIsPinnedTo: {8} (a{17}) private void LinkVideoCodecDirectoryToApi(IHasDirectory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { codec.CurrentDirectoryResultIsNotDirectoryRoot.LinkComplementInputSig( - trilist.BooleanInput[joinMap.DirectoryIsRoot.JoinNumber]); - - trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot); + trilist.BooleanInput[joinMap.DirectoryIsRoot.JoinNumber]); trilist.SetStringSigAction(joinMap.DirectorySearchString.JoinNumber, codec.SearchDirectory); @@ -951,8 +949,25 @@ ScreenIndexIsPinnedTo: {8} (a{17}) trilist.SetSigFalseAction(joinMap.DirectoryFolderBack.JoinNumber, codec.GetDirectoryParentFolderContents); + if (codec.DirectoryRoot != null) + { + trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)codec.DirectoryRoot.CurrentDirectoryResults.Count); + + var clearBytes = XSigHelpers.ClearOutputs(); + + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); + + Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length); + + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); + } + codec.DirectoryResultReturned += (sender, args) => { + Debug.Console(2, this, "CiscoLinkToApi > DirectoryResultReturnedHandler"); + trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)args.Directory.CurrentDirectoryResults.Count); var clearBytes = XSigHelpers.ClearOutputs(); @@ -961,6 +976,8 @@ ScreenIndexIsPinnedTo: {8} (a{17}) Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); var directoryXSig = UpdateDirectoryXSig(args.Directory, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); + Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); }; } @@ -1068,10 +1085,14 @@ ScreenIndexIsPinnedTo: {8} (a{17}) var contactIndex = 1; var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count]; + Debug.Console(2, this, "Is root {0} Directory Count: {1}", isRoot, directory.CurrentDirectoryResults.Count); + foreach (var entry in directory.CurrentDirectoryResults) { var arrayIndex = contactIndex - 1; + Debug.Console(2, this, "Entry Name: {0}, Folder ID: {1}", entry.Name, entry.FolderId); + if (entry is DirectoryFolder && entry.ParentFolderId == "root") { tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, String.Format("[+] {0}", entry.Name)); @@ -1081,7 +1102,11 @@ ScreenIndexIsPinnedTo: {8} (a{17}) continue; } - if (isRoot && String.IsNullOrEmpty(entry.FolderId)) continue; + //if (isRoot && String.IsNullOrEmpty(entry.FolderId)) { continue; } + //else + //{ + // Debug.Console(2, this, "Skipping Entry"); + //} tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, entry.Name); @@ -1628,20 +1653,31 @@ ScreenIndexIsPinnedTo: {8} (a{17}) // Update the call history joins var maxItems = joinMap.RecentCallNamesStart.JoinSpan; - uint i = 0; - foreach(var item in codec.CallHistory.RecentCalls) + // Create history + uint index = 0; + for (uint i = 0; i < maxItems && i < codec.CallHistory.RecentCalls.Count; i++) { - trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, item.Name); - trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, item.StartTime.ToShortTimeString()); - trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)item.OccurrenceType); - i++; + trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].Name); + trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].StartTime.ToShortTimeString()); + trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)codec.CallHistory.RecentCalls[(int)i].OccurrenceType); + //i++; + index = i; } + + //foreach(var item in codec.CallHistory.RecentCalls) + //{ + // trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, item.Name); + // trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, item.StartTime.ToShortTimeString()); + // trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)item.OccurrenceType); + // i++; + //} - for (uint index = i; i < maxItems; index++) + // Clears existing items + for (uint j = index; j < maxItems; j++) { - trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + index, string.Empty); - trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + index, string.Empty); - trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + index, 0); + trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + j, string.Empty); + trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + j, string.Empty); + trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + j, 0); } } From 84b39a959edb5ac5571a3878bfccb31403ba79d6 Mon Sep 17 00:00:00 2001 From: Jonathan Arndt Date: Tue, 8 Feb 2022 16:31:18 -0800 Subject: [PATCH 023/202] Update VideoCodecBase class UpdateDirectoryXSig method removing the check if the FolderId is null or empty as that check would be device specific --- .../VideoCodec/VideoCodecBase.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index f60ece74..fd24c8ec 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -966,8 +966,6 @@ ScreenIndexIsPinnedTo: {8} (a{17}) codec.DirectoryResultReturned += (sender, args) => { - Debug.Console(2, this, "CiscoLinkToApi > DirectoryResultReturnedHandler"); - trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)args.Directory.CurrentDirectoryResults.Count); var clearBytes = XSigHelpers.ClearOutputs(); @@ -1102,12 +1100,6 @@ ScreenIndexIsPinnedTo: {8} (a{17}) continue; } - //if (isRoot && String.IsNullOrEmpty(entry.FolderId)) { continue; } - //else - //{ - // Debug.Console(2, this, "Skipping Entry"); - //} - tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, entry.Name); contactIndex++; From 402754b69e199dd1c219dddebe47f737e83896a2 Mon Sep 17 00:00:00 2001 From: Jonathan Arndt Date: Tue, 8 Feb 2022 16:31:26 -0800 Subject: [PATCH 024/202] Update VideoCodecBase class UpdateDirectoryXSig method removing the check if the FolderId is null or empty as that check would be device specific --- .../Essentials Devices Common/VideoCodec/VideoCodecBase.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index fd24c8ec..490d5abb 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1100,6 +1100,12 @@ ScreenIndexIsPinnedTo: {8} (a{17}) continue; } + //if (isRoot && String.IsNullOrEmpty(entry.FolderId)) { continue; } + //else + //{ + // Debug.Console(2, this, "Skipping Entry"); + //} + tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, entry.Name); contactIndex++; From faabdde3f78c5901e2cfe8341b2bc4cff052e91e Mon Sep 17 00:00:00 2001 From: Jonathan Arndt Date: Tue, 8 Feb 2022 16:31:45 -0800 Subject: [PATCH 025/202] Update VideoCodecBase class UpdateDirectoryXSig method removing the check if the FolderId is null or empty as that check would be device specific --- .../Essentials Devices Common/VideoCodec/VideoCodecBase.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 490d5abb..fd24c8ec 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1100,12 +1100,6 @@ ScreenIndexIsPinnedTo: {8} (a{17}) continue; } - //if (isRoot && String.IsNullOrEmpty(entry.FolderId)) { continue; } - //else - //{ - // Debug.Console(2, this, "Skipping Entry"); - //} - tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, entry.Name); contactIndex++; From c84525ddefed71d2ba65571dfa8b614d8af6f5ac Mon Sep 17 00:00:00 2001 From: Jonathan Arndt Date: Wed, 9 Feb 2022 11:39:35 -0800 Subject: [PATCH 026/202] Update recent call history and call method to protect for zero value from SIMPL --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 2 +- .../VideoCodec/VideoCodecBase.cs | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index efe1914d..74f4b919 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -1516,7 +1516,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco return; } - SendText(string.Format("xConfiguration Audio SoundsAndAlerts RingVolume: [0]", volume)); + SendText(string.Format("xConfiguration Audio SoundsAndAlerts RingVolume: {0}", volume)); } /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index fd24c8ec..fcdcc127 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -982,6 +982,8 @@ ScreenIndexIsPinnedTo: {8} (a{17}) private void SelectDirectoryEntry(IHasDirectory codec, ushort i, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { + if (i < 1 || i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return; + var entry = codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1]; if (entry is DirectoryFolder) @@ -1047,10 +1049,12 @@ ScreenIndexIsPinnedTo: {8} (a{17}) const int offset = maxStrings; var stringIndex = 0; var arrayIndex = 0; - var tokenArray = new XSigToken[contact.ContactMethods.Count]; + // Create a new token array and set the size to the number of methods times the total number of signals + var tokenArray = new XSigToken[maxMethods * offset]; + + Debug.Console(2, this, "Creating XSIG token array with size {0}", maxMethods * offset); // TODO: Add code to generate XSig data - foreach (var method in contact.ContactMethods) { if (arrayIndex >= maxMethods * offset) @@ -1606,11 +1610,17 @@ ScreenIndexIsPinnedTo: {8} (a{17}) // Selected item action and feedback trilist.SetUShortSigAction(joinMap.SelectRecentCallItem.JoinNumber, (u) => { + if (u == 0 || u > codec.CallHistory.RecentCalls.Count) + { + Debug.Console(2, this, "Recent Call History index out of range"); + return; + } + _selectedRecentCallItemIndex = (int)(u - 1); - trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, u); + trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, u); var _selectedRecentCallItem = codec.CallHistory.RecentCalls[_selectedRecentCallItemIndex]; - + if (_selectedRecentCallItem != null) { trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, _selectedRecentCallItem.Name); From db982f449095cb337057043bacc6b3ef6e96075e Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 14:00:49 -0700 Subject: [PATCH 027/202] feat(essentials): Adds ability to select and dial contact methods for directory contacts via SIMPL bridge --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 28 ++++++++ .../VideoCodec/VideoCodecBase.cs | 70 ++++++++++++++----- 2 files changed, 80 insertions(+), 18 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 368a547f..51b30c6a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -510,6 +510,20 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("DirectoryDialSelectedContactMethod")] + public JoinDataComplete DirectoryDialSelectedContactMethod = new JoinDataComplete( + new JoinData + { + JoinNumber = 108, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to dial the selected contact method", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("CameraTiltUp")] public JoinDataComplete CameraTiltUp = new JoinDataComplete( new JoinData @@ -1232,6 +1246,20 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Analog }); + [JoinName("SelectContactMethod")] + public JoinDataComplete SelectContactMethod = new JoinDataComplete( + new JoinData + { + JoinNumber = 103, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selects a contact method by index", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + [JoinName("CameraPresetSelect")] public JoinDataComplete CameraPresetSelect = new JoinDataComplete( new JoinData diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index fcdcc127..55063eab 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -980,52 +980,86 @@ ScreenIndexIsPinnedTo: {8} (a{17}) }; } + + private void SelectDirectoryEntry(IHasDirectory codec, ushort i, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { if (i < 1 || i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return; - var entry = codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1]; + _selectedDirectoryItem = codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1]; - if (entry is DirectoryFolder) + + if (_selectedDirectoryItem is DirectoryFolder) { - codec.GetDirectoryFolderContents(entry.FolderId); + codec.GetDirectoryFolderContents(_selectedDirectoryItem.FolderId); trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0); - return; + trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, _selectedDirectoryItem.Name); + trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty); + trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber); + return; } - // Allow auto dial of selected line + // not a folder. Clear this value + trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, string.Empty); + + var selectedContact = _selectedDirectoryItem as DirectoryContact; + if (selectedContact != null) + { + trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, selectedContact.Name); + + } + + // Allow auto dial of selected line. Always dials first contact method if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber)) { - var dialableEntry = entry as IInvitableContact; + var invitableEntry = _selectedDirectoryItem as IInvitableContact; - if (dialableEntry != null) - { - Dial(dialableEntry); - return; - } + if (invitableEntry != null) + { + Dial(invitableEntry); + return; + } - var entryToDial = entry as DirectoryContact; + var entryToDial = _selectedDirectoryItem as DirectoryContact; - if (entryToDial == null) return; + trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber, selectedContact.ContactMethods[0].Number); - Dial(entryToDial.ContactMethods[0].Number); + if (entryToDial == null) return; + + Dial(entryToDial.ContactMethods[0].Number); return; } else { // If auto dial is disabled... - var entryToDial = entry as DirectoryContact; + var entryToDial = _selectedDirectoryItem as DirectoryContact; if (entryToDial == null) { + // Clear out values and actions from last selected item trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0); + trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty); + trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber); return; } - trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedLine.JoinNumber, () => Dial(entryToDial.ContactMethods[0].Number)); - trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, (ushort)entryToDial.ContactMethods.Count); + // Update the action to dial the selected contact method + trilist.SetUShortSigAction(joinMap.SelectContactMethod.JoinNumber, (u) => + { + if (u < 1 || u > entryToDial.ContactMethods.Count) return; + + trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber, () => Dial(entryToDial.ContactMethods[u].Number)); + }); + + // Sets DirectoryDialSelectedLine join action to dial first contact method + trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedLine.JoinNumber, () => Dial(entryToDial.ContactMethods[0].Number)); + var clearBytes = XSigHelpers.ClearOutputs(); trilist.SetString(joinMap.ContactMethods.JoinNumber, @@ -1034,7 +1068,6 @@ ScreenIndexIsPinnedTo: {8} (a{17}) trilist.SetString(joinMap.ContactMethods.JoinNumber, contactMethodsXSig); } - } /// @@ -1599,6 +1632,7 @@ ScreenIndexIsPinnedTo: {8} (a{17}) // Following fields only used for Bridging private int _selectedRecentCallItemIndex; private CodecCallHistory.CallHistoryEntry _selectedRecentCallItem; + private DirectoryItem _selectedDirectoryItem; private void LinkVideoCodecCallHistoryToApi(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { From db526cdd40d1cffd7cd2741c0711f46c50f7c320 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 14:09:54 -0700 Subject: [PATCH 028/202] fix(essentials): fixes exception when parsing presentation local instance ghosted response --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 74f4b919..36192f7d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -830,15 +830,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco if (conference.Presentation.LocalInstance.Count > 0) { if (!string.IsNullOrEmpty(conference.Presentation.LocalInstance[0].ghost)) + { _presentationSource = 0; + _presentationLocalOnly = false; + _presentationLocalRemote = false; + } else if (conference.Presentation.LocalInstance[0].Source != null) { _presentationSource = conference.Presentation.LocalInstance[0].Source.IntValue; + _presentationLocalOnly = conference.Presentation.LocalInstance.Any((i) => i.SendingMode.LocalOnly); + _presentationLocalRemote = conference.Presentation.LocalInstance.Any((i) => i.SendingMode.LocalRemote); } - _presentationLocalOnly = conference.Presentation.LocalInstance.Any((i) => i.SendingMode.LocalOnly); - _presentationLocalRemote = conference.Presentation.LocalInstance.Any((i) => i.SendingMode.LocalRemote); - PresentationSourceFeedback.FireUpdate(); PresentationSendingLocalOnlyFeedback.FireUpdate(); PresentationSendingLocalRemoteFeedback.FireUpdate(); From b97783603b28a403ce5072992145ab3fbbe9d69d Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 14:14:44 -0700 Subject: [PATCH 029/202] feat(essentials): Adds analog fb join for recent calls count to VideoCodecControllerJoinMap and bridge --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 14 ++++++++++++++ .../VideoCodec/VideoCodecBase.cs | 1 + 2 files changed, 15 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 51b30c6a..03d0c4b5 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -1358,6 +1358,20 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Analog }); + [JoinName("RecentCallCount")] + public JoinDataComplete RecentCallCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 191, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Recent Call Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + #endregion diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 55063eab..c32643ba 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1685,6 +1685,7 @@ ScreenIndexIsPinnedTo: {8} (a{17}) trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); // + trilist.SetUshort(joinMap.RecentCallCount.JoinNumber, (ushort)codec.CallHistory.RecentCalls.Count); // Update the call history joins var maxItems = joinMap.RecentCallNamesStart.JoinSpan; From adbce916baa322f83fbb5a2ce36d4d8157cc5b10 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 14:34:25 -0700 Subject: [PATCH 030/202] feat(essentials): Adds ability to read camera info from codec rather than just from config --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 26 ++++++++++++++++++- .../VideoCodec/CiscoCodec/xStatus.cs | 14 ++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 36192f7d..213a8d7c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -646,7 +646,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// void SyncState_InitialSyncCompleted(object sender, EventArgs e) { - SetUpCameras(_config.CameraInfo); + // Check for camera config info first + if (_config.CameraInfo.Count > 0) + { + SetUpCameras(_config.CameraInfo); + } + else + { + try + { + var cameraInfo = new List(); + + foreach (var camera in CodecStatus.Status.Cameras.Camera) + { + var id = Convert.ToUInt16(camera.id); + var info = new CameraInfo() { CameraNumber = id, Name = string.Format("{0} {1}", camera.Manufacturer, camera.Model), SourceId = camera.DetectedConnector.ConnectorId }; + cameraInfo.Add(info); + } + } + catch (Exception ex) + { + Debug.Console(2, this, "Error generating camera info from codec status data: {0}", ex); + } + } + + // Fire the ready event SetIsReady(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index 6db3c2e3..e7f418eb 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -262,11 +262,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public string Value { get; set; } } + public class DectectedConnector + { + public string Value { get; set; } + + public int ConnectorId + { + get + { + return Convert.ToUInt16(Value); + } + } + } + public class Camera { public string id { get; set; } public Capabilities Capabilities { get; set; } public Connected Connected { get; set; } + public DectectedConnector DetectedConnector { get; set; } public Flip Flip { get; set; } public HardwareID HardwareID { get; set; } public MacAddress MacAddress { get; set; } From 90023621dc7929db042a0ae50cc2a96603013e09 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 14:48:45 -0700 Subject: [PATCH 031/202] fix(essentials): Adds some better console log comments and calls SetUpCameras() after reading data from codec. --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 213a8d7c..39b3e167 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -649,10 +649,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco // Check for camera config info first if (_config.CameraInfo.Count > 0) { + Debug.Console(0, this, "Reading codec cameraInfo from config properties."); SetUpCameras(_config.CameraInfo); } else { + Debug.Console(0, this, "No cameraInfo defined in video codec config. Attempting to get camera info from codec status data"); try { var cameraInfo = new List(); @@ -663,6 +665,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco var info = new CameraInfo() { CameraNumber = id, Name = string.Format("{0} {1}", camera.Manufacturer, camera.Model), SourceId = camera.DetectedConnector.ConnectorId }; cameraInfo.Add(info); } + + Debug.Console(0, this, "Successfully got cameraInfo for {0} cameras from codec.", cameraInfo.Count); + + SetUpCameras(cameraInfo); } catch (Exception ex) { @@ -670,10 +676,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } } - - - // Fire the ready event - SetIsReady(); //CommDebuggingIsOn = false; GetCallHistory(); @@ -683,6 +685,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco BookingsRefreshTimer = new CTimer(GetBookings, 900000, 900000); // 15 minute timer to check for new booking info GetBookings(null); + + // Fire the ready event + SetIsReady(); } public void SetCommDebug(string s) @@ -2003,6 +2008,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco SelectedCameraFeedback = new StringFeedback(() => SelectedCamera.Key); + SelectedCamera = Cameras[0]; ; // call the method to select the camera and ensure the feedbacks get updated. + ControllingFarEndCameraFeedback = new BoolFeedback(() => SelectedCamera is IAmFarEndCamera); DeviceManager.AddDevice(farEndCamera); @@ -2018,7 +2025,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco FarEndRoomPresets.Add(new CodecRoomPreset(i, label, true, false)); } - SelectedCamera = Cameras[0]; ; // call the method to select the camera and ensure the feedbacks get updated. } #region IHasCodecCameras Members From 89a7f2aa800c18a2657a4b543224412ad3a12055 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 14:54:19 -0700 Subject: [PATCH 032/202] fix(essentials): Add a condition to check for an empty configuration.presentation object response and return to avoid null ref ex --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 39b3e167..d9baa070 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -856,6 +856,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco // Check to see if the message contains /Status/Conference/Presentation/LocalInstance and extract source value var conference = tempCodecStatus.Status.Conference; + if (conference.Presentation != null && conference.Presentation.LocalInstance == null) + { + // Handles an empty presentation object response + return; + } + if (conference.Presentation.LocalInstance.Count > 0) { if (!string.IsNullOrEmpty(conference.Presentation.LocalInstance[0].ghost)) From 70c5df90400de3675d55683734a89ed182b8ef5e Mon Sep 17 00:00:00 2001 From: Jonathan Arndt Date: Wed, 9 Feb 2022 14:09:07 -0800 Subject: [PATCH 033/202] Removed add camera to device manager --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index d9baa070..0140142d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -2003,8 +2003,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco camera.SetCapabilites(cam.Capabilities.Options.Value); } - Cameras.Add(camera); - DeviceManager.AddDevice(camera); + Cameras.Add(camera); } } @@ -2012,13 +2011,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco var farEndCamera = new CiscoFarEndCamera(Key + "-cameraFar", "Far End", this); Cameras.Add(farEndCamera); - SelectedCameraFeedback = new StringFeedback(() => SelectedCamera.Key); + SelectedCameraFeedback = new StringFeedback(() => SelectedCamera.Key); - SelectedCamera = Cameras[0]; ; // call the method to select the camera and ensure the feedbacks get updated. - - ControllingFarEndCameraFeedback = new BoolFeedback(() => SelectedCamera is IAmFarEndCamera); - - DeviceManager.AddDevice(farEndCamera); + ControllingFarEndCameraFeedback = new BoolFeedback(() => SelectedCamera is IAmFarEndCamera); NearEndPresets = new List(15); @@ -2031,6 +2026,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco FarEndRoomPresets.Add(new CodecRoomPreset(i, label, true, false)); } + SelectedCamera = Cameras[0]; ; // call the method to select the camera and ensure the feedbacks get updated. + } #region IHasCodecCameras Members From 9d80954214181b55fd84e2a21709b614f8c14d28 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 15:10:39 -0700 Subject: [PATCH 034/202] fix(essentials): Adds check for SendingMode property value before attempting to set fb --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 9 +++++++-- .../VideoCodec/CiscoCodec/xStatus.cs | 6 ++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 0140142d..51141051 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -873,8 +873,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco else if (conference.Presentation.LocalInstance[0].Source != null) { _presentationSource = conference.Presentation.LocalInstance[0].Source.IntValue; - _presentationLocalOnly = conference.Presentation.LocalInstance.Any((i) => i.SendingMode.LocalOnly); - _presentationLocalRemote = conference.Presentation.LocalInstance.Any((i) => i.SendingMode.LocalRemote); + + // Check for any values in the SendingMode property + if (conference.Presentation.LocalInstance.Any((i) => !string.IsNullOrEmpty(i.SendingMode.Value))) + { + _presentationLocalOnly = conference.Presentation.LocalInstance.Any((i) => i.SendingMode.LocalOnly); + _presentationLocalRemote = conference.Presentation.LocalInstance.Any((i) => i.SendingMode.LocalRemote); + } } PresentationSourceFeedback.FireUpdate(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index e7f418eb..19208c73 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -596,6 +596,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { get { + if(string.IsNullOrEmpty(_Value)) + return false; + return _Value.ToLower() == "localonly"; } } @@ -604,6 +607,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { get { + if(string.IsNullOrEmpty(_Value)) + return false; + return _Value.ToLower() == "localremote"; } } From e24965eb54afd3124f7b3b4a1d58bcf5b54d6a2d Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 15:37:55 -0700 Subject: [PATCH 035/202] fix(essentials): fixes ValueChagnedAction to run both feedback updates instead of one --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 51141051..53776000 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -456,8 +456,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco CodecStatus.Status.Video.Selfview.Mode.ValueChangedAction = SelfviewIsOnFeedback.FireUpdate; CodecStatus.Status.Video.Selfview.PIPPosition.ValueChangedAction = ComputeSelfviewPipStatus; CodecStatus.Status.Video.Layout.LayoutFamily.Local.ValueChangedAction = ComputeLocalLayout; - CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = SharingContentIsOnFeedback.FireUpdate; - CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = FarEndIsSharingContentFeedback.FireUpdate; + CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = () => + { + SharingContentIsOnFeedback.FireUpdate(); + FarEndIsSharingContentFeedback.FireUpdate(); + }; CodecStatus.Status.Conference.DoNotDisturb.ValueChangedAction = DoNotDisturbModeIsOnFeedback.FireUpdate; CodecConfiguration.Configuration.Audio.SoundsAndAlerts.RingVolume.ValueChangedAction = RingtoneVolumeFeedback.FireUpdate; From 7dd6b3a9b643d57bba2355bb01a6760a06928afa Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 16:31:31 -0700 Subject: [PATCH 036/202] fix(essentials): fixes index off by 1 error and updates call status to check for "OnHold" as status value --- .../Bridges/JoinMaps/VideoCodecControllerJoinMap.cs | 10 +++++----- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 1 + .../VideoCodec/CiscoCodec/xStatus.cs | 4 ++++ .../VideoCodec/VideoCodecBase.cs | 7 +++++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 03d0c4b5..1d6657ca 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -240,7 +240,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps new JoinMetadata { Description = "Speed Dial", - JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); @@ -940,7 +940,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps new JoinMetadata { Description = "Pulse to remove the selected recent call item specified by the SelectRecentCallItem analog join", - JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); @@ -954,7 +954,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps new JoinMetadata { Description = "Pulse to dial the selected recent call item specified by the SelectRecentCallItem analog join", - JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); @@ -1037,8 +1037,8 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Holds Call at specified index", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + Description = "Holds Call at specified index. FB reported on Call Status XSIG", + JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 53776000..2d4ec0d6 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -909,6 +909,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco if (!string.IsNullOrEmpty(call.Status.Value)) { tempActiveCall.Status = CodecCallStatus.ConvertToStatusEnum(call.Status.Value); + tempActiveCall.IsOnHold = call.Status.OnHold; if (newStatus == eCodecCallStatus.Connected) GetCallHistory(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index 19208c73..d6de0d4b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -317,6 +317,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco string _Value; public bool BoolValue { get; private set; } + public bool OnHold { get; private set; } + public string Value { get @@ -328,6 +330,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco // If the incoming value is "Active" it sets the BoolValue true, otherwise sets it false _Value = value; BoolValue = value == "Active"; + OnHold = value == "OnHold"; OnValueChanged(); } } @@ -2099,6 +2102,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco CallType = new CallType(); Status = new Status2(); Duration = new Duration(); + PlacedOnHold = new PlacedOnHold(); } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index c32643ba..670111e9 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1054,7 +1054,7 @@ ScreenIndexIsPinnedTo: {8} (a{17}) { if (u < 1 || u > entryToDial.ContactMethods.Count) return; - trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber, () => Dial(entryToDial.ContactMethods[u].Number)); + trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber, () => Dial(entryToDial.ContactMethods[u - 1].Number)); }); // Sets DirectoryDialSelectedLine join action to dial first contact method @@ -1216,7 +1216,7 @@ ScreenIndexIsPinnedTo: {8} (a{17}) var holdCodec = this as IHasCallHold; if (holdCodec != null) { - for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++) + for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++) { trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + i), () => { @@ -1245,6 +1245,9 @@ ScreenIndexIsPinnedTo: {8} (a{17}) }); } } + + + } private string UpdateCallStatusXSig() From 102ae3ad4f44da8fcb3dbb5bd143ca0488a625a6 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 16:41:37 -0700 Subject: [PATCH 037/202] fix(essentials): second attempt to get on hold fb working --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 2 +- .../VideoCodec/CiscoCodec/xStatus.cs | 28 ++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 2d4ec0d6..bf067570 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -909,7 +909,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco if (!string.IsNullOrEmpty(call.Status.Value)) { tempActiveCall.Status = CodecCallStatus.ConvertToStatusEnum(call.Status.Value); - tempActiveCall.IsOnHold = call.Status.OnHold; + tempActiveCall.IsOnHold = tempActiveCall.Status == eCodecCallStatus.OnHold; if (newStatus == eCodecCallStatus.Connected) GetCallHistory(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index d6de0d4b..9b45d3ce 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -312,12 +312,33 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } } + public class CallStatus : ValueProperty + { + string _Value; + public bool BoolValue { get; private set; } + + + public string Value + { + get + { + return _Value; + } + set + { + // If the incoming value is "Active" it sets the BoolValue true, otherwise sets it false + _Value = value; + BoolValue = value == "Connected"; + OnValueChanged(); + } + } + } + public class Status2 : ValueProperty { string _Value; public bool BoolValue { get; private set; } - public bool OnHold { get; private set; } public string Value { @@ -330,7 +351,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco // If the incoming value is "Active" it sets the BoolValue true, otherwise sets it false _Value = value; BoolValue = value == "Active"; - OnHold = value == "OnHold"; OnValueChanged(); } } @@ -2094,13 +2114,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public Protocol Protocol { get; set; } public ReceiveCallRate ReceiveCallRate { get; set; } public RemoteNumber RemoteNumber { get; set; } - public Status2 Status { get; set; } + public CallStatus Status { get; set; } public TransmitCallRate TransmitCallRate { get; set; } public Call() { CallType = new CallType(); - Status = new Status2(); + Status = new CallStatus(); Duration = new Duration(); PlacedOnHold = new PlacedOnHold(); } From db67f97a1f5ae8b618c387df6eba2b7d737ffa2a Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 16:46:19 -0700 Subject: [PATCH 038/202] fix(essentials): add local scope variable for indexer in hold/resume call loop --- .../VideoCodec/VideoCodecBase.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 670111e9..37cbebd4 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1218,9 +1218,13 @@ ScreenIndexIsPinnedTo: {8} (a{17}) { for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++) { - trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + i), () => + var index = i; + + trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + index), () => { - var call = ActiveCalls[i]; + if (index < 0 || index >= ActiveCalls.Count) return; + + var call = ActiveCalls[index]; if (call != null) { holdCodec.HoldCall(call); @@ -1231,9 +1235,11 @@ ScreenIndexIsPinnedTo: {8} (a{17}) } }); - trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + i), () => + trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + index), () => { - var call = ActiveCalls[i]; + if (index < 0 || index >= ActiveCalls.Count) return; + + var call = ActiveCalls[index]; if (call != null) { holdCodec.ResumeCall(call); From 7a2e99f145f388ea739e2d1b83d17ddf888a9080 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 16:50:06 -0700 Subject: [PATCH 039/202] feat(essentials): Adds HoldAllCalls join and action --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 14 ++++++++++++++ .../VideoCodec/VideoCodecBase.cs | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 1d6657ca..8f7e8188 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -1028,6 +1028,20 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("HoldAllCalls")] + public JoinDataComplete HoldAllCalls = new JoinDataComplete( + new JoinData + { + JoinNumber = 220, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Holds all calls", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("HoldCallsStart")] public JoinDataComplete HoldCallsStart = new JoinDataComplete( new JoinData diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 37cbebd4..821a46d5 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1216,6 +1216,14 @@ ScreenIndexIsPinnedTo: {8} (a{17}) var holdCodec = this as IHasCallHold; if (holdCodec != null) { + trilist.SetSigFalseAction(joinMap.HoldAllCalls.JoinNumber, () => + { + foreach (var call in ActiveCalls) + { + holdCodec.HoldCall(call); + } + }); + for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++) { var index = i; From bfdc882eb61cecbb7ff7f7df9fe822ff2e5ec3f0 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 17:07:18 -0700 Subject: [PATCH 040/202] fix(essentials): Adds logic to recover from malformed json response on initial communication. Adds better formatting for active calls list print to console --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 10 ++++++++++ .../VideoCodec/VideoCodecBase.cs | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index bf067570..567d49dc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -1182,6 +1182,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } catch (Exception ex) { + if (ex is Newtonsoft.Json.JsonReaderException) + { + Debug.Console(1, this, "Received malformed response from codec. Unable to serialize. Disconnecting and attmpting to recconnect"); + + Communication.Disconnect(); + + Initialize(); + } + + Debug.Console(1, this, "Error Deserializing feedback from codec: {0}", ex); } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 821a46d5..0d1df28f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -257,10 +257,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public virtual void ListCalls() { + Debug.Console(1, this, "Active Calls:"); + var sb = new StringBuilder(); foreach (var c in ActiveCalls) { - sb.AppendFormat("{0} {1} -- {2} {3}\n", c.Id, c.Number, c.Name, c.Status); + sb.AppendFormat("id: {0} number: {1} -- name: {2} status: {3} onHold: {4}\r\n", c.Id, c.Number, c.Name, c.Status, c.IsOnHold); } Debug.Console(1, this, "\n{0}\n", sb.ToString()); } From b0288951eb24954e4043bac781926cb08968a8cd Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 17:15:58 -0700 Subject: [PATCH 041/202] fix(essentials): removes logic to disconnect and reinitialize on malformed json response --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 567d49dc..fce15e76 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -1182,17 +1182,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } catch (Exception ex) { + Debug.Console(1, this, "Error Deserializing feedback from codec: {0}", ex); + if (ex is Newtonsoft.Json.JsonReaderException) { - Debug.Console(1, this, "Received malformed response from codec. Unable to serialize. Disconnecting and attmpting to recconnect"); + Debug.Console(1, this, "Received malformed response from codec. Unable to deserialize. Disconnecting and attmpting to recconnect"); - Communication.Disconnect(); + //Communication.Disconnect(); - Initialize(); + //Initialize(); } - - Debug.Console(1, this, "Error Deserializing feedback from codec: {0}", ex); } } From e4a4564bbc49f76b605c797f9ea70db21c0e126e Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 17:21:19 -0700 Subject: [PATCH 042/202] fix(essentials): Attempts to set OnHold an alternative way --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index fce15e76..9d6ddc71 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -909,7 +909,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco if (!string.IsNullOrEmpty(call.Status.Value)) { tempActiveCall.Status = CodecCallStatus.ConvertToStatusEnum(call.Status.Value); - tempActiveCall.IsOnHold = tempActiveCall.Status == eCodecCallStatus.OnHold; + if (tempActiveCall.Status == eCodecCallStatus.OnHold) + { + tempActiveCall.IsOnHold = true; + } if (newStatus == eCodecCallStatus.Connected) GetCallHistory(); @@ -1186,7 +1189,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco if (ex is Newtonsoft.Json.JsonReaderException) { - Debug.Console(1, this, "Received malformed response from codec. Unable to deserialize. Disconnecting and attmpting to recconnect"); + Debug.Console(1, this, "Received malformed response from codec."); //Communication.Disconnect(); From 0bb4b6edd4938e2f399aef5183c102baad3b90fe Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 17:30:26 -0700 Subject: [PATCH 043/202] fix(essentials): doh! fixes issue where IsOnHold would get set to false if response contains no PlacedOhHold object --- .../Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index 9b45d3ce..daaf8709 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -2122,7 +2122,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco CallType = new CallType(); Status = new CallStatus(); Duration = new Duration(); - PlacedOnHold = new PlacedOnHold(); } } From cb3c80ff8ffd6b829c239f41f22ee1eb4d386901 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Feb 2022 17:44:53 -0700 Subject: [PATCH 044/202] fix(essentials): fixes to on hold feedback and call status xsig --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 7 ++----- .../VideoCodec/VideoCodecBase.cs | 11 ++++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 9d6ddc71..32aaaa21 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -909,11 +909,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco if (!string.IsNullOrEmpty(call.Status.Value)) { tempActiveCall.Status = CodecCallStatus.ConvertToStatusEnum(call.Status.Value); - if (tempActiveCall.Status == eCodecCallStatus.OnHold) - { - tempActiveCall.IsOnHold = true; - } - + tempActiveCall.IsOnHold = tempActiveCall.Status == eCodecCallStatus.OnHold; + if (newStatus == eCodecCallStatus.Connected) GetCallHistory(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 0d1df28f..07c62144 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1270,7 +1270,8 @@ ScreenIndexIsPinnedTo: {8} (a{17}) { const int maxCalls = 8; const int maxStrings = 6; - const int offset = 6; + const int maxDigitals = 2; + const int offset = maxStrings + maxDigitals; var stringIndex = 0; var digitalIndex = maxStrings * maxCalls; var arrayIndex = 0; @@ -1282,8 +1283,8 @@ ScreenIndexIsPinnedTo: {8} (a{17}) if (arrayIndex >= maxCalls * offset) break; //digitals - tokenArray[arrayIndex] = new XSigDigitalToken(digitalIndex + 1, call.IsActiveCall); - tokenArray[arrayIndex + 1] = new XSigDigitalToken(digitalIndex + 2, call.IsOnHold); + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, call.IsActiveCall); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, call.IsOnHold); //serials tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); @@ -1305,8 +1306,8 @@ ScreenIndexIsPinnedTo: {8} (a{17}) while (digitalIndex < maxCalls) { //digitals - tokenArray[arrayIndex] = new XSigDigitalToken(digitalIndex + 1, false); - tokenArray[arrayIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); //serials From 79a3a8ed7ef6efb81a8c490db8e4ad23185e6984 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 10 Feb 2022 15:49:53 -0700 Subject: [PATCH 045/202] fix(essentials): #901 Overhaul's feedback processing for efficiency Updates to address changes to ZRAAPI v1.1 and ZoomRooms 5.9.4 --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 174 +++++++++++++++--- packages.config | 2 +- 2 files changed, 152 insertions(+), 24 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index ef3b59cb..adc2e79d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -32,8 +32,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private const long MeetingRefreshTimer = 60000; public uint DefaultMeetingDurationMin { get; private set; } - private const string Delimiter = "\x0D\x0A"; + /// + /// CR LF + /// + private const string EchoDelimiter = "\x0D\x0A\x0D\x0A"; + private const string SendDelimiter = "\x0D"; + + /// + /// CR LF } CR LF + /// + private const string JsonDelimiter = "\x0D\x0A\x7D\x0D\x0A"; + + private string[] Delimiters = new string[] { EchoDelimiter, JsonDelimiter, "OK\x0D\x0A", "end\x0D\x0A" }; + //"echo off\x0D\x0A\x0A\x0D\x0A" private readonly GenericQueue _receiveQueue; //private readonly CrestronQueue _receiveQueue; @@ -71,7 +83,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom else { CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, - "zStatus SystemUnit\r"); + "zStatus SystemUnit" + SendDelimiter); } DeviceManager.AddDevice(CommunicationMonitor); @@ -86,9 +98,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom _syncState.InitialSyncCompleted += SyncState_InitialSyncCompleted; + _syncState.FirstJsonResponseReceived += (o, a) => SetUpSyncQueries(); + PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); - PortGather = new CommunicationGather(Communication, "\x0A") {IncludeDelimiter = true}; + PortGather = new CommunicationGather(Communication, Delimiters) {IncludeDelimiter = true}; PortGather.LineReceived += Port_LineReceived; CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, @@ -904,7 +918,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Debug.Console(1, this, "Sending: '{0}'", command); } - Communication.SendText(command + Delimiter); + Communication.SendText(command + SendDelimiter); } /// @@ -914,13 +928,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args) { - //if (CommDebuggingIsOn) - // Debug.Console(1, this, "Gathered: '{0}'", args.Text); + //Debug.Console(0, this, "Port_LineReceived"); - _receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessMessage)); + if (args.Delimiter != JsonDelimiter) + { +// Debug.Console(0, this, +//@"Non JSON response: +//Delimiter: {0} +//{1}", ComTextHelper.GetDebugText(args.Delimiter), args.Text); + ProcessNonJsonResponse(args.Text); + return; + } + else + { +// Debug.Console(0, this, +//@"JSON response: +//Delimiter: {0} +//{1}", ComTextHelper.GetDebugText(args.Delimiter), args.Text); + _receiveQueue.Enqueue(new ProcessStringMessage(args.Text, DeserializeResponse)); + //_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessMessage)); + } } - /// /// Queues the initial queries to be sent upon connection /// @@ -979,6 +1008,84 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom _syncState.StartSync(); } + private void SetupSession() + { + // disable echo of commands + SendText("echo off"); + // switch to json format + // set feedback exclusions + // Currently the feedback exclusions don't work when using the API in JSON response mode + // But leave these here in case the API gets updated in the future + // These may work as of 5.9.4 + if (_props.DisablePhonebookAutoDownload) + { + SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); + } + SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list"); + SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list"); + SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist"); + + SendText("zStatus SystemUnit"); + } + + /// + /// Processes non-JSON responses as their are received + /// + /// + private void ProcessNonJsonResponse(string response) + { + if (response.Contains("client_loop: send disconnect: Broken pipe")) + { + Debug.Console(1, this, Debug.ErrorLogLevel.Error, + "Zoom Room Controller or App connected. Essentials will NOT control the Zoom Room until it is disconnected."); + + return; + } + + if (!_syncState.InitialSyncComplete) + { + if(response.ToLower().Contains("*r login successful")) + { + _syncState.LoginResponseReceived(); + + SendText("format json"); + + SetupSession(); + } + + //switch (response.Trim().ToLower()) // remove the whitespace + //{ + // case "*r login successful": + // { + // _syncState.LoginMessageReceived(); + + // //// Fire up a thread to send the intial commands. + // //CrestronInvoke.BeginInvoke(o => + // //{ + // // disable echo of commands + // SendText("echo off"); + // // switch to json format + // SendText("format json"); + // // set feedback exclusions + // // Currently the feedback exclusions don't work when using the API in JSON response mode + // // But leave these here in case the API gets updated in the future + // // These may work as of 5.9.4 + // if (_props.DisablePhonebookAutoDownload) + // { + // SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); + // } + // SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list"); + // SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list"); + // SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist"); + + // //}); + + // break; + // } + //} + } + } + /// /// Processes messages as they are dequeued /// @@ -1006,7 +1113,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom //Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter); - if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + Delimiter) + if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + EchoDelimiter) // Check for the beginning of a new JSON message { _jsonFeedbackMessageIsIncoming = true; @@ -1023,7 +1130,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom return; } - if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + Delimiter) + if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + EchoDelimiter) // Check for the end of a JSON message { _jsonMessage.Append(message); @@ -1068,7 +1175,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { case "*r login successful": { - _syncState.LoginMessageReceived(); + _syncState.LoginResponseReceived(); // Fire up a thread to send the intial commands. @@ -1121,6 +1228,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var message = JObject.Parse(trimmedResponse); + if (!_syncState.FirstJsonResponseWasReceived) + { + _syncState.ReceivedFirstJsonResponse(); + } + var eType = (eZoomRoomResponseType) Enum.Parse(typeof (eZoomRoomResponseType), message["type"].Value(), true); @@ -1642,19 +1754,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { case "login": { - _syncState.LoginMessageReceived(); + _syncState.LoginResponseReceived(); - if (!_syncState.InitialQueryMessagesWereSent) - { - SetUpSyncQueries(); - } + SetupSession(); JsonConvert.PopulateObject(responseObj.ToString(), Status.Login); break; } case "systemunit": - { + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit); break; @@ -3437,7 +3547,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } - public bool LoginMessageWasReceived { get; private set; } + public bool LoginResponseWasReceived { get; private set; } + + public bool FirstJsonResponseWasReceived { get; private set; } public bool InitialQueryMessagesWereSent { get; private set; } @@ -3453,6 +3565,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public event EventHandler InitialSyncCompleted; + public event EventHandler FirstJsonResponseReceived; + public void StartSync() { DequeueQueries(); @@ -3475,13 +3589,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom _syncQueries.Enqueue(query); } - public void LoginMessageReceived() + public void LoginResponseReceived() { - LoginMessageWasReceived = true; - Debug.Console(1, this, "Login Message Received."); + LoginResponseWasReceived = true; + Debug.Console(1, this, "Login Rsponse Received."); CheckSyncStatus(); } + public void ReceivedFirstJsonResponse() + { + FirstJsonResponseWasReceived = true; + Debug.Console(1, this, "First JSON Response Received."); + + var handler = FirstJsonResponseReceived; + if (handler != null) + { + handler(this, null); + } + CheckSyncStatus(); + } + public void InitialQueryMessagesSent() { InitialQueryMessagesWereSent = true; @@ -3506,7 +3633,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void CodecDisconnected() { _syncQueries.Clear(); - LoginMessageWasReceived = false; + LoginResponseWasReceived = false; + FirstJsonResponseWasReceived = false; InitialQueryMessagesWereSent = false; LastQueryResponseWasReceived = false; CamerasHaveBeenSetUp = false; @@ -3515,7 +3643,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void CheckSyncStatus() { - if (LoginMessageWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived && + if (LoginResponseWasReceived && FirstJsonResponseWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived && CamerasHaveBeenSetUp) { InitialSyncComplete = true; diff --git a/packages.config b/packages.config index 10124bbd..41f858a6 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From 348981d8cbc294d0cf426c7ea6db7b546cbb6572 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 10 Feb 2022 17:33:06 -0700 Subject: [PATCH 046/202] fix(essntials): Fixes exception in OnLayoutChanged and fixes debug JSON formatting for Zoom responses --- .../Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 01c53ab7..f3891dde 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -1241,7 +1241,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var responseObj = message[topKey]; - Debug.Console(1, "{0} Response Received. topKey: '{1}'\n{2}", eType, topKey, responseObj.ToString()); + Debug.Console(1, this, "{0} Response Received. topKey: '{1}'\n{2}", eType, topKey, responseObj.ToString().Replace("\n", CrestronEnvironment.NewLine)); switch (eType) { @@ -3170,7 +3170,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom handler(this, new LayoutInfoChangedEventArgs() { AvailableLayouts = AvailableLayouts, - CurrentSelectedLayout = (zConfiguration.eLayoutStyle)Enum.Parse(typeof(zConfiguration.eLayoutStyle),LocalLayoutFeedback.StringValue, true), + CurrentSelectedLayout = (zConfiguration.eLayoutStyle)Enum.Parse(typeof(zConfiguration.eLayoutStyle),string.IsNullOrEmpty(LocalLayoutFeedback.StringValue) ? "None" : LocalLayoutFeedback.StringValue , true), LayoutViewIsOnFirstPage = LayoutViewIsOnFirstPageFeedback.BoolValue, LayoutViewIsOnLastPage = LayoutViewIsOnLastPageFeedback.BoolValue, CanSwapContentWithThumbnail = CanSwapContentWithThumbnailFeedback.BoolValue, From 0e5cecbfc3e885c6797deb6a2aafbca7f8f97e2c Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 11 Feb 2022 14:16:40 -0700 Subject: [PATCH 047/202] fix(essentials): #901 Refines initial synchronization sequence Makes sure that the AddedContact feedback subscription is excluded right away, but later included after the phonebook is retrieved. This should ensure we get the initial phonebook and all subsequent additions at runtime while also minimizing initial data volume. --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index f3891dde..1db04f0c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -102,6 +102,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); + PhonebookSyncState.InitialSyncCompleted += (o, a) => ResubscribeForAddedContacts(); + PortGather = new CommunicationGather(Communication, Delimiters) {IncludeDelimiter = true}; PortGather.LineReceived += Port_LineReceived; @@ -1017,10 +1019,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // Currently the feedback exclusions don't work when using the API in JSON response mode // But leave these here in case the API gets updated in the future // These may work as of 5.9.4 - if (_props.DisablePhonebookAutoDownload) - { - SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); - } + + // In 5.9.4 we're getting sent an AddedContact message for every contact in the phonebook on connect, which is redunant and way too much data + // We want to exclude these messages right away until after we've retrieved the entire phonebook and then we can re-enable them + SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); + SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list"); SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list"); SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist"); @@ -1028,6 +1031,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SendText("zStatus SystemUnit"); } + /// + /// Removes the feedback exclusion for added contacts + /// + private void ResubscribeForAddedContacts() + { + SendText("zFeedback Register Op: in Path: /Event/Phonebook/AddedContact"); + } + /// /// Processes non-JSON responses as their are received /// From b0e3fddec78aefee57713b5a8f46f1efa5767c9e Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 11 Feb 2022 15:50:09 -0700 Subject: [PATCH 048/202] fix(essentials): fixes issue with local var scope when assigning actions for ending individual calls Fixes Incoming call name/number feedback in bridge --- .../VideoCodec/VideoCodecBase.cs | 84 +++++++++++-------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 07c62144..a96de4f9 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -680,37 +680,37 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (meetingIndex >= maxParticipants * offset) break; - Debug.Console(2, this, -@"Updating Participant on xsig: -Name: {0} (s{9}) -AudioMute: {1} (d{10}) -VideoMute: {2} (d{11}) -CanMuteVideo: {3} (d{12}) -CanUMuteVideo: {4} (d{13}) -IsHost: {5} (d{14}) -HandIsRaised: {6} (d{15}) -IsPinned: {7} (d{16}) -ScreenIndexIsPinnedTo: {8} (a{17}) -", - participant.Name, - participant.AudioMuteFb, - participant.VideoMuteFb, - participant.CanMuteVideo, - participant.CanUnmuteVideo, - participant.IsHost, - participant.HandIsRaisedFb, - participant.IsPinnedFb, - participant.ScreenIndexIsPinnedToFb, - stringIndex + 1, - digitalIndex + 1, - digitalIndex + 2, - digitalIndex + 3, - digitalIndex + 4, - digitalIndex + 5, - digitalIndex + 6, - digitalIndex + 7, - analogIndex + 1 - ); +// Debug.Console(2, this, +//@"Updating Participant on xsig: +//Name: {0} (s{9}) +//AudioMute: {1} (d{10}) +//VideoMute: {2} (d{11}) +//CanMuteVideo: {3} (d{12}) +//CanUMuteVideo: {4} (d{13}) +//IsHost: {5} (d{14}) +//HandIsRaised: {6} (d{15}) +//IsPinned: {7} (d{16}) +//ScreenIndexIsPinnedTo: {8} (a{17}) +//", +// participant.Name, +// participant.AudioMuteFb, +// participant.VideoMuteFb, +// participant.CanMuteVideo, +// participant.CanUnmuteVideo, +// participant.IsHost, +// participant.HandIsRaisedFb, +// participant.IsPinnedFb, +// participant.ScreenIndexIsPinnedToFb, +// stringIndex + 1, +// digitalIndex + 1, +// digitalIndex + 2, +// digitalIndex + 3, +// digitalIndex + 4, +// digitalIndex + 5, +// digitalIndex + 6, +// digitalIndex + 7, +// analogIndex + 1 +// ); //digitals @@ -1160,7 +1160,9 @@ ScreenIndexIsPinnedTo: {8} (a{17}) { trilist.SetSigFalseAction((uint)(joinMap.EndCallStart.JoinNumber + i), () => { - var call = ActiveCalls[i]; + var callIndex = i; + + var call = ActiveCalls[callIndex]; if (call != null) { EndCall(call); @@ -1182,11 +1184,19 @@ ScreenIndexIsPinnedTo: {8} (a{17}) Debug.Console(1, this, "Call is incoming: {0}", args.CallItem.Direction == eCodecCallDirection.Incoming); trilist.SetBool(joinMap.IncomingCall.JoinNumber, args.CallItem.Direction == eCodecCallDirection.Incoming && args.CallItem.Status == eCodecCallStatus.Ringing); - if (args.CallItem.Direction == eCodecCallDirection.Incoming) - { - trilist.SetSigFalseAction(joinMap.IncomingAnswer.JoinNumber, () => AcceptCall(args.CallItem)); - trilist.SetSigFalseAction(joinMap.IncomingReject.JoinNumber, () => RejectCall(args.CallItem)); - } + if (args.CallItem.Direction == eCodecCallDirection.Incoming) + { + trilist.SetSigFalseAction(joinMap.IncomingAnswer.JoinNumber, () => AcceptCall(args.CallItem)); + trilist.SetSigFalseAction(joinMap.IncomingReject.JoinNumber, () => RejectCall(args.CallItem)); + trilist.SetString(joinMap.IncomingCallName.JoinNumber, args.CallItem.Name); + trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, args.CallItem.Number); + } + else + { + trilist.SetString(joinMap.IncomingCallName.JoinNumber, string.Empty); + trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, string.Empty); + } + trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); From d88a454499c5213d47febceb558d28448889297b Mon Sep 17 00:00:00 2001 From: Jonathan Arndt Date: Fri, 11 Feb 2022 16:39:47 -0800 Subject: [PATCH 049/202] fix(essentials): various bug fixes for hold FB, individual call end, incoming name-number fb, ipv4 address fb --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 27 ++++++++++++++----- .../VideoCodec/CiscoCodec/xConfiguration.cs | 11 ++++++++ .../VideoCodec/CiscoCodec/xStatus.cs | 25 ++++++++++++++++- .../VideoCodec/VideoCodecBase.cs | 9 ++++++- 4 files changed, 64 insertions(+), 8 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 32aaaa21..e42386c8 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -664,8 +664,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco foreach (var camera in CodecStatus.Status.Cameras.Camera) { + Debug.Console(0, this, +@"Camera id: {0} +Name: {1} +ConnectorID: {2}" +, camera.id +, camera.Manufacturer.Value +, camera.Model.Value); + var id = Convert.ToUInt16(camera.id); - var info = new CameraInfo() { CameraNumber = id, Name = string.Format("{0} {1}", camera.Manufacturer, camera.Model), SourceId = camera.DetectedConnector.ConnectorId }; + var info = new CameraInfo() { CameraNumber = id, Name = string.Format("{0} {1}", camera.Manufacturer.Value, camera.Model.Value), SourceId = camera.DetectedConnector.ConnectorId }; cameraInfo.Add(info); } @@ -1994,7 +2002,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } Cameras.Add(internalCamera); - DeviceManager.AddDevice(internalCamera); + //DeviceManager.AddDevice(internalCamera); } else { @@ -2132,12 +2140,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { get { - if (CodecConfiguration.Configuration.Network != null) + var address = string.Empty; + if (CodecConfiguration.Configuration.Network.Count > 0) { - if (CodecConfiguration.Configuration.Network.Count > 0) - return CodecConfiguration.Configuration.Network[0].IPv4.Address.Value; + if(!string.IsNullOrEmpty(CodecConfiguration.Configuration.Network[0].IPv4.Address.Value)) + address = CodecConfiguration.Configuration.Network[0].IPv4.Address.Value; } - return string.Empty; + + if (string.IsNullOrEmpty(address) && CodecStatus.Status.Network.Count > 0) + { + if(!string.IsNullOrEmpty(CodecStatus.Status.Network[0].IPv4.Address.Value)) + address = CodecStatus.Status.Network[0].IPv4.Address.Value; + } + return address; } } public override string E164Alias diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs index 3a8c6252..05c07378 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xConfiguration.cs @@ -738,6 +738,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public Assignment Assignment { get; set; } public Gateway Gateway { get; set; } public SubnetMask SubnetMask { get; set; } + + public IPv4() + { + Address = new Address4(); + } } public class Address5 @@ -889,6 +894,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public RemoteAccess RemoteAccess { get; set; } public Speed Speed { get; set; } public VLAN VLAN { get; set; } + + public Network() + { + IPv4 = new IPv4(); + } } public class Mode19 @@ -1850,6 +1860,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { Audio = new Audio(); Conference = new Conference(); + Network = new List(); } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index daaf8709..5bde30ff 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -270,7 +270,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { get { - return Convert.ToUInt16(Value); + if(!string.IsNullOrEmpty(Value)) + { + return Convert.ToUInt16(Value); + } + else + return -1; } } } @@ -289,6 +294,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public Position Position { get; set; } public SerialNumber SerialNumber { get; set; } public SoftwareID SoftwareID { get; set; } + + public Camera() + { + Manufacturer = new Manufacturer(); + Model = new Model(); + DetectedConnector = new DectectedConnector(); + } } public class Availability : ValueProperty @@ -957,6 +969,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public Address4 Address { get; set; } public Gateway Gateway { get; set; } public SubnetMask SubnetMask { get; set; } + + public IPv4() + { + Address = new Address4(); + } } public class Address5 @@ -999,6 +1016,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public IPv4 IPv4 { get; set; } public IPv6 IPv6 { get; set; } public VLAN VLAN { get; set; } + + public Network() + { + IPv4 = new IPv4(); + } } public class CurrentAddress @@ -2222,6 +2244,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco SystemUnit = new SystemUnit(); Video = new Video(); Conference = new Conference2(); + Network = new List(); } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index a96de4f9..73390b06 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1158,9 +1158,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //End a specific call, specified by index. Maximum 8 calls supported for (int i = 0; i < joinMap.EndCallStart.JoinSpan; i++) { + var callIndex = i; + trilist.SetSigFalseAction((uint)(joinMap.EndCallStart.JoinNumber + i), () => { - var callIndex = i; + + if (callIndex < 0 || callIndex >= ActiveCalls.Count) + { + Debug.Console(2, this, "Cannot end call. No call found at index: {0}", callIndex); + return; + } var call = ActiveCalls[callIndex]; if (call != null) From e39c76001ac27a57dbde1e1f62133a3e384e23ab Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 14 Feb 2022 16:16:58 -0700 Subject: [PATCH 050/202] feat(essentials): Updates to initial sync mechanism Adds queue for all outgoing commands to codec that blocks until sync is established --- .../VideoCodec/CiscoCodec/CiscoCamera.cs | 40 ++-- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 198 +++++++++++------- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 2 +- 3 files changed, 147 insertions(+), 93 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCamera.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCamera.cs index 67312df8..9e8b0554 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCamera.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCamera.cs @@ -41,12 +41,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public void PanLeft() { - ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Left CallId: {0}", CallId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: Left CallId: {0}", CallId)); } public void PanRight() { - ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Right CallId: {0}", CallId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: Right CallId: {0}", CallId)); } public void PanStop() @@ -60,12 +60,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public void TiltDown() { - ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Down CallId: {0}", CallId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: Down CallId: {0}", CallId)); } public void TiltUp() { - ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Up CallId: {0}", CallId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: Up CallId: {0}", CallId)); } public void TiltStop() @@ -79,12 +79,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public void ZoomIn() { - ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomIn CallId: {0}", CallId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomIn CallId: {0}", CallId)); } public void ZoomOut() { - ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomOut CallId: {0}", CallId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomOut CallId: {0}", CallId)); } public void ZoomStop() @@ -97,7 +97,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco void Stop() { - ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Stop CallId: {0}", CallId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Stop CallId: {0}", CallId)); } public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) @@ -202,7 +202,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { if (!isMoving) { - ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Left PanSpeed: {1}", CameraId, PanSpeed)); + ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Left PanSpeed: {1}", CameraId, PanSpeed)); isPanning = true; } } @@ -211,14 +211,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { if (!isMoving) { - ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Right PanSpeed: {1}", CameraId, PanSpeed)); + ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Right PanSpeed: {1}", CameraId, PanSpeed)); isPanning = true; } } public void PanStop() { - ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Stop", CameraId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Stop", CameraId)); isPanning = false; } @@ -232,7 +232,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { if (!isMoving) { - ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Down TiltSpeed: {1}", CameraId, TiltSpeed)); + ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Down TiltSpeed: {1}", CameraId, TiltSpeed)); isTilting = true; } } @@ -241,14 +241,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { if (!isMoving) { - ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Up TiltSpeed: {1}", CameraId, TiltSpeed)); + ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Up TiltSpeed: {1}", CameraId, TiltSpeed)); isTilting = true; } } public void TiltStop() { - ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Stop", CameraId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Stop", CameraId)); isTilting = false; } @@ -260,7 +260,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { if (!isMoving) { - ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: In ZoomSpeed: {1}", CameraId, ZoomSpeed)); + ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: In ZoomSpeed: {1}", CameraId, ZoomSpeed)); isZooming = true; } } @@ -269,14 +269,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { if (!isMoving) { - ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Out ZoomSpeed: {1}", CameraId, ZoomSpeed)); + ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Out ZoomSpeed: {1}", CameraId, ZoomSpeed)); isZooming = true; } } public void ZoomStop() { - ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Stop", CameraId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Stop", CameraId)); isZooming = false; } @@ -288,7 +288,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { if (!isMoving) { - ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Near", CameraId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Near", CameraId)); isFocusing = true; } } @@ -297,20 +297,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { if (!isMoving) { - ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Far", CameraId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Far", CameraId)); isFocusing = true; } } public void FocusStop() { - ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Stop", CameraId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Stop", CameraId)); isFocusing = false; } public void TriggerAutoFocus() { - ParentCodec.SendText(string.Format("xCommand Camera TriggerAutofocus CameraId: {0}", CameraId)); + ParentCodec.EnqueueCommand(string.Format("xCommand Camera TriggerAutofocus CameraId: {0}", CameraId)); } #endregion diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index e42386c8..b6f59dac 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -371,7 +371,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco _phonebookMode = props.PhonebookMode; - _syncState = new CodecSyncState(Key + "--Sync"); + _syncState = new CodecSyncState(Key + "--Sync", this); PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); @@ -547,7 +547,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// Mobile Control user code private void DisplayUserCode(string code) { - SendText(string.Format("xcommand userinterface message alert display title:\"Mobile Control User Code:\" text:\"{0}\" duration: 30", code)); + EnqueueCommand(string.Format("xcommand userinterface message alert display title:\"Mobile Control User Code:\" text:\"{0}\" duration: 30", code)); } private void SendMcBrandingUrl(IMobileControlRoomBridge mcBridge) @@ -559,17 +559,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco Debug.Console(1, this, "Sending url: {0}", mcBridge.QrCodeUrl); - SendText("xconfiguration userinterface custommessage: \"Scan the QR code with a mobile phone to get started\""); - SendText("xconfiguration userinterface osd halfwakemessage: \"Tap the touch panel or scan the QR code with a mobile phone to get started\""); + EnqueueCommand("xconfiguration userinterface custommessage: \"Scan the QR code with a mobile phone to get started\""); + EnqueueCommand("xconfiguration userinterface osd halfwakemessage: \"Tap the touch panel or scan the QR code with a mobile phone to get started\""); var checksum = !String.IsNullOrEmpty(mcBridge.QrCodeChecksum) ? String.Format("checksum: {0} ", mcBridge.QrCodeChecksum) : String.Empty; - SendText(String.Format( + EnqueueCommand(String.Format( "xcommand userinterface branding fetch {1}type: branding url: {0}", mcBridge.QrCodeUrl, checksum)); - SendText(String.Format( + EnqueueCommand(String.Format( "xcommand userinterface branding fetch {1}type: halfwakebranding url: {0}", mcBridge.QrCodeUrl, checksum)); } @@ -578,9 +578,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { Debug.Console(1, this, "Sending url: {0}", _brandingUrl); - SendText(String.Format("xcommand userinterface branding fetch type: branding url: {0}", + EnqueueCommand(String.Format("xcommand userinterface branding fetch type: branding url: {0}", _brandingUrl)); - SendText(String.Format("xcommand userinterface branding fetch type: halfwakebranding url: {0}", + EnqueueCommand(String.Format("xcommand userinterface branding fetch type: halfwakebranding url: {0}", _brandingUrl)); } /// @@ -769,6 +769,12 @@ ConnectorID: {2}" Debug.Console(1, this, "RX: '{0}'", args.Text); } + if(args.Text.Contains("xCommand")) + { + Debug.Console(2, this, "Received command echo response. Ignoring"); + return; + } + if (args.Text == "{" + Delimiter) // Check for the beginning of a new JSON message { _jsonFeedbackMessageIsIncoming = true; @@ -813,6 +819,7 @@ ConnectorID: {2}" if(_loginMessageReceivedTimer != null) _loginMessageReceivedTimer.Stop(); + SendText("echo off"); SendText("xPreferences outputmode json"); break; } @@ -829,12 +836,21 @@ ConnectorID: {2}" } } } - - } /// - /// Appends the delimiter and send the command to the codec + /// Enqueues a command to be sent to the codec. + /// + /// + public void EnqueueCommand(string command) + { + _syncState.AddCommandToQueue(command + Delimiter); + } + + /// + /// Appends the delimiter and send the command to the codec. + /// Should not be used for sending general commands to the codec. Use EnqueueCommand instead. + /// Should be used to get initial Status and Configuration as well as set up Feedback Registration /// /// public void SendText(string command) @@ -1062,7 +1078,9 @@ ConnectorID: {2}" _syncState.InitialStatusMessageReceived(); if (!_syncState.InitialConfigurationMessageWasReceived) + { SendText("xConfiguration"); + } } } else if (response.IndexOf("\"Configuration\":{") > -1 || response.IndexOf("\"Configuration\": {") > -1) @@ -1296,7 +1314,7 @@ ConnectorID: {2}" public void GetCallHistory() { - SendText("xCommand CallHistory Recents Limit: 20 Order: OccurrenceTime"); + EnqueueCommand("xCommand CallHistory Recents Limit: 20 Order: OccurrenceTime"); } /// @@ -1315,7 +1333,7 @@ ConnectorID: {2}" { Debug.Console(1, this, "Retrieving Booking Info from Codec. Current Time: {0}", DateTime.Now.ToLocalTime()); - SendText("xCommand Bookings List Days: 1 DayOffset: 0"); + EnqueueCommand("xCommand Bookings List Days: 1 DayOffset: 0"); } /// @@ -1349,13 +1367,13 @@ ConnectorID: {2}" private void GetPhonebookFolders() { // Get Phonebook Folders (determine local/corporate from config, and set results limit) - SendText(string.Format("xCommand Phonebook Search PhonebookType: {0} ContactType: Folder", _phonebookMode)); + EnqueueCommand(string.Format("xCommand Phonebook Search PhonebookType: {0} ContactType: Folder", _phonebookMode)); } private void GetPhonebookContacts() { // Get Phonebook Folders (determine local/corporate from config, and set results limit) - SendText(string.Format("xCommand Phonebook Search PhonebookType: {0} ContactType: Contact Limit: {1}", _phonebookMode, _phonebookResultsLimit)); + EnqueueCommand(string.Format("xCommand Phonebook Search PhonebookType: {0} ContactType: Contact Limit: {1}", _phonebookMode, _phonebookResultsLimit)); } /// @@ -1364,7 +1382,7 @@ ConnectorID: {2}" /// public void SearchDirectory(string searchString) { - SendText(string.Format("xCommand Phonebook Search SearchString: \"{0}\" PhonebookType: {1} ContactType: Contact Limit: {2}", searchString, _phonebookMode, _phonebookResultsLimit)); + EnqueueCommand(string.Format("xCommand Phonebook Search SearchString: \"{0}\" PhonebookType: {1} ContactType: Contact Limit: {2}", searchString, _phonebookMode, _phonebookResultsLimit)); } /// @@ -1373,7 +1391,7 @@ ConnectorID: {2}" /// public void GetDirectoryFolderContents(string folderId) { - SendText(string.Format("xCommand Phonebook Search FolderId: {0} PhonebookType: {1} ContactType: Any Limit: {2}", folderId, _phonebookMode, _phonebookResultsLimit)); + EnqueueCommand(string.Format("xCommand Phonebook Search FolderId: {0} PhonebookType: {1} ContactType: Any Limit: {2}", folderId, _phonebookMode, _phonebookResultsLimit)); } /// @@ -1444,7 +1462,7 @@ ConnectorID: {2}" /// public override void Dial(string number) { - SendText(string.Format("xCommand Dial Number: \"{0}\"", number)); + EnqueueCommand(string.Format("xCommand Dial Number: \"{0}\"", number)); } /// @@ -1469,43 +1487,43 @@ ConnectorID: {2}" /// public void Dial(string number, string protocol, string callRate, string callType, string meetingId) { - SendText(string.Format("xCommand Dial Number: \"{0}\" Protocol: {1} CallRate: {2} CallType: {3} BookingId: {4}", number, protocol, callRate, callType, meetingId)); + EnqueueCommand(string.Format("xCommand Dial Number: \"{0}\" Protocol: {1} CallRate: {2} CallType: {3} BookingId: {4}", number, protocol, callRate, callType, meetingId)); } public override void EndCall(CodecActiveCallItem activeCall) { - SendText(string.Format("xCommand Call Disconnect CallId: {0}", activeCall.Id)); + EnqueueCommand(string.Format("xCommand Call Disconnect CallId: {0}", activeCall.Id)); } public override void EndAllCalls() { foreach (CodecActiveCallItem activeCall in ActiveCalls) { - SendText(string.Format("xCommand Call Disconnect CallId: {0}", activeCall.Id)); + EnqueueCommand(string.Format("xCommand Call Disconnect CallId: {0}", activeCall.Id)); } } public override void AcceptCall(CodecActiveCallItem item) { - SendText("xCommand Call Accept"); + EnqueueCommand("xCommand Call Accept"); } public override void RejectCall(CodecActiveCallItem item) { - SendText("xCommand Call Reject"); + EnqueueCommand("xCommand Call Reject"); } #region IHasCallHold Members public void HoldCall(CodecActiveCallItem activeCall) { - SendText(string.Format("xCommand Call Hold CallId: {0}", activeCall.Id)); + EnqueueCommand(string.Format("xCommand Call Hold CallId: {0}", activeCall.Id)); } public void ResumeCall(CodecActiveCallItem activeCall) { - SendText(string.Format("xCommand Call Resume CallId: {0}", activeCall.Id)); + EnqueueCommand(string.Format("xCommand Call Resume CallId: {0}", activeCall.Id)); } #endregion @@ -1514,7 +1532,7 @@ ConnectorID: {2}" public void JoinCall(CodecActiveCallItem activeCall) { - SendText(string.Format("xCommand Call Join CallId: {0}", activeCall.Id)); + EnqueueCommand(string.Format("xCommand Call Join CallId: {0}", activeCall.Id)); } public void JoinAllCalls() @@ -1531,7 +1549,7 @@ ConnectorID: {2}" if (ids.Length > 0) { - SendText(string.Format("xCommand Call Join {0}", ids.ToString())); + EnqueueCommand(string.Format("xCommand Call Join {0}", ids.ToString())); } } @@ -1543,7 +1561,7 @@ ConnectorID: {2}" /// public override void SendDtmf(string s) { - SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", GetCallId(), s)); + EnqueueCommand(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", GetCallId(), s)); } /// @@ -1553,7 +1571,7 @@ ConnectorID: {2}" /// public override void SendDtmf(string s, CodecActiveCallItem activeCall) { - SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", activeCall.Id, s)); + EnqueueCommand(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", activeCall.Id, s)); } public void SelectPresentationSource(int source) @@ -1581,7 +1599,7 @@ ConnectorID: {2}" return; } - SendText(string.Format("xConfiguration Audio SoundsAndAlerts RingVolume: {0}", volume)); + EnqueueCommand(string.Format("xConfiguration Audio SoundsAndAlerts RingVolume: {0}", volume)); } /// @@ -1615,7 +1633,7 @@ ConnectorID: {2}" sendingMode = "LocalOnly"; if (_desiredPresentationSource > 0) - SendText(string.Format("xCommand Presentation Start PresentationSource: {0} SendingMode: {1}", _desiredPresentationSource, sendingMode)); + EnqueueCommand(string.Format("xCommand Presentation Start PresentationSource: {0} SendingMode: {1}", _desiredPresentationSource, sendingMode)); } /// @@ -1625,39 +1643,39 @@ ConnectorID: {2}" { _desiredPresentationSource = 0; - SendText("xCommand Presentation Stop"); + EnqueueCommand("xCommand Presentation Stop"); } public override void PrivacyModeOn() { - SendText("xCommand Audio Microphones Mute"); + EnqueueCommand("xCommand Audio Microphones Mute"); } public override void PrivacyModeOff() { - SendText("xCommand Audio Microphones Unmute"); + EnqueueCommand("xCommand Audio Microphones Unmute"); } public override void PrivacyModeToggle() { - SendText("xCommand Audio Microphones ToggleMute"); + EnqueueCommand("xCommand Audio Microphones ToggleMute"); } public override void MuteOff() { - SendText("xCommand Audio Volume Unmute"); + EnqueueCommand("xCommand Audio Volume Unmute"); } public override void MuteOn() { - SendText("xCommand Audio Volume Mute"); + EnqueueCommand("xCommand Audio Volume Mute"); } public override void MuteToggle() { - SendText("xCommand Audio Volume ToggleMute"); + EnqueueCommand("xCommand Audio Volume ToggleMute"); } /// @@ -1666,7 +1684,7 @@ ConnectorID: {2}" /// public override void VolumeUp(bool pressRelease) { - SendText("xCommand Audio Volume Increase"); + EnqueueCommand("xCommand Audio Volume Increase"); } /// @@ -1675,7 +1693,7 @@ ConnectorID: {2}" /// public override void VolumeDown(bool pressRelease) { - SendText("xCommand Audio Volume Decrease"); + EnqueueCommand("xCommand Audio Volume Decrease"); } /// @@ -1685,7 +1703,7 @@ ConnectorID: {2}" public override void SetVolume(ushort level) { var scaledLevel = CrestronEnvironment.ScaleWithLimits(level, 65535, 0, 100, 0); - SendText(string.Format("xCommand Audio Volume Set Level: {0}", scaledLevel)); + EnqueueCommand(string.Format("xCommand Audio Volume Set Level: {0}", scaledLevel)); } /// @@ -1693,7 +1711,7 @@ ConnectorID: {2}" /// public void VolumeSetToDefault() { - SendText("xCommand Audio Volume SetToDefault"); + EnqueueCommand("xCommand Audio Volume SetToDefault"); } /// @@ -1701,7 +1719,7 @@ ConnectorID: {2}" /// public override void StandbyActivate() { - SendText("xCommand Standby Activate"); + EnqueueCommand("xCommand Standby Activate"); } /// @@ -1709,7 +1727,7 @@ ConnectorID: {2}" /// public override void StandbyDeactivate() { - SendText("xCommand Standby Deactivate"); + EnqueueCommand("xCommand Standby Deactivate"); } public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) @@ -1736,7 +1754,7 @@ ConnectorID: {2}" public void LinkCiscoCodecToApi(BasicTriList trilist, CiscoCodecJoinMap joinMap) { // Custom commands to codec - trilist.SetStringSigAction(joinMap.CommandToDevice.JoinNumber, (s) => this.SendText(s)); + trilist.SetStringSigAction(joinMap.CommandToDevice.JoinNumber, (s) => this.EnqueueCommand(s)); var dndCodec = this as IHasDoNotDisturbMode; @@ -1780,7 +1798,7 @@ ConnectorID: {2}" /// public void Reboot() { - SendText("xCommand SystemUnit Boot Action: Restart"); + EnqueueCommand("xCommand SystemUnit Boot Action: Restart"); } /// @@ -1806,7 +1824,7 @@ ConnectorID: {2}" /// public void SelfViewModeOn() { - SendText("xCommand Video Selfview Set Mode: On"); + EnqueueCommand("xCommand Video Selfview Set Mode: On"); } /// @@ -1814,7 +1832,7 @@ ConnectorID: {2}" /// public void SelfViewModeOff() { - SendText("xCommand Video Selfview Set Mode: Off"); + EnqueueCommand("xCommand Video Selfview Set Mode: Off"); } /// @@ -1829,7 +1847,7 @@ ConnectorID: {2}" else mode = "On"; - SendText(string.Format("xCommand Video Selfview Set Mode: {0}", mode)); + EnqueueCommand(string.Format("xCommand Video Selfview Set Mode: {0}", mode)); } /// @@ -1838,7 +1856,7 @@ ConnectorID: {2}" /// public void SelfviewPipPositionSet(CodecCommandWithLabel position) { - SendText(string.Format("xCommand Video Selfview Set Mode: On PIPPosition: {0}", position.Command)); + EnqueueCommand(string.Format("xCommand Video Selfview Set Mode: On PIPPosition: {0}", position.Command)); } /// @@ -1863,7 +1881,7 @@ ConnectorID: {2}" /// public void LocalLayoutSet(CodecCommandWithLabel layout) { - SendText(string.Format("xCommand Video Layout LayoutFamily Set Target: local LayoutFamily: {0}", layout.Command)); + EnqueueCommand(string.Format("xCommand Video Layout LayoutFamily Set Target: local LayoutFamily: {0}", layout.Command)); } /// @@ -1907,7 +1925,7 @@ ConnectorID: {2}" else _currentPresentationView = "Maximized"; - SendText(string.Format("xCommand Video PresentationView Set View: {0}", _currentPresentationView)); + EnqueueCommand(string.Format("xCommand Video PresentationView Set View: {0}", _currentPresentationView)); PresentationViewMaximizedFeedback.FireUpdate(); } @@ -1935,7 +1953,7 @@ ConnectorID: {2}" public void RemoveCallHistoryEntry(CodecCallHistory.CallHistoryEntry entry) { - SendText(string.Format("xCommand CallHistory DeleteEntry CallHistoryId: {0} AcknowledgeConsecutiveDuplicates: True", entry.OccurrenceHistoryId)); + EnqueueCommand(string.Format("xCommand CallHistory DeleteEntry CallHistoryId: {0} AcknowledgeConsecutiveDuplicates: True", entry.OccurrenceHistoryId)); } #region IHasCameraSpeakerTrack @@ -1944,11 +1962,11 @@ ConnectorID: {2}" { if (!CameraAutoModeIsOnFeedback.BoolValue) { - SendText("xCommand Cameras SpeakerTrack Activate"); + EnqueueCommand("xCommand Cameras SpeakerTrack Activate"); } else { - SendText("xCommand Cameras SpeakerTrack Deactivate"); + EnqueueCommand("xCommand Cameras SpeakerTrack Deactivate"); } } @@ -1959,7 +1977,7 @@ ConnectorID: {2}" CameraMuteOff(); } - SendText("xCommand Cameras SpeakerTrack Activate"); + EnqueueCommand("xCommand Cameras SpeakerTrack Activate"); } public void CameraAutoModeOff() @@ -1969,7 +1987,7 @@ ConnectorID: {2}" CameraMuteOff(); } - SendText("xCommand Cameras SpeakerTrack Deactivate"); + EnqueueCommand("xCommand Cameras SpeakerTrack Deactivate"); } #endregion @@ -2106,7 +2124,7 @@ ConnectorID: {2}" var ciscoCam = camera as CiscoSparkCamera; if (ciscoCam != null) { - SendText(string.Format("xCommand Video Input SetMainVideoSource SourceId: {0}", ciscoCam.CameraId)); + EnqueueCommand(string.Format("xCommand Video Input SetMainVideoSource SourceId: {0}", ciscoCam.CameraId)); } } @@ -2259,19 +2277,19 @@ ConnectorID: {2}" if (SelectedCamera is IAmFarEndCamera) SelectFarEndPreset(preset); else - SendText(string.Format("xCommand RoomPreset Activate PresetId: {0}", preset)); + EnqueueCommand(string.Format("xCommand RoomPreset Activate PresetId: {0}", preset)); } public void CodecRoomPresetStore(int preset, string description) { - SendText(string.Format("xCommand RoomPreset Store PresetId: {0} Description: \"{1}\" Type: All", preset, description)); + EnqueueCommand(string.Format("xCommand RoomPreset Store PresetId: {0} Description: \"{1}\" Type: All", preset, description)); } #endregion public void SelectFarEndPreset(int preset) { - SendText(string.Format("xCommand Call FarEndControl RoomPreset Activate CallId: {0} PresetId: {1}", GetCallId(), preset)); + EnqueueCommand(string.Format("xCommand Call FarEndControl RoomPreset Activate CallId: {0} PresetId: {1}", GetCallId(), preset)); } @@ -2308,7 +2326,7 @@ ConnectorID: {2}" { id = 3; } - SendText(string.Format("xCommand UserInterface Presentation ExternalSource Add ConnectorId: {0} SourceIdentifier: \"{1}\" Name: \"{2}\" Type: {3}", id, key, name, type.ToString())); + EnqueueCommand(string.Format("xCommand UserInterface Presentation ExternalSource Add ConnectorId: {0} SourceIdentifier: \"{1}\" Name: \"{2}\" Type: {3}", id, key, name, type.ToString())); // SendText(string.Format("xCommand UserInterface Presentation ExternalSource State Set SourceIdentifier: \"{0}\" State: Ready", key)); Debug.Console(2, this, "Adding ExternalSource {0} {1}", connectorId, name); @@ -2322,14 +2340,14 @@ ConnectorID: {2}" /// public void SetExternalSourceState(string key, eExternalSourceMode mode) { - SendText(string.Format("xCommand UserInterface Presentation ExternalSource State Set SourceIdentifier: \"{0}\" State: {1}", key, mode.ToString())); + EnqueueCommand(string.Format("xCommand UserInterface Presentation ExternalSource State Set SourceIdentifier: \"{0}\" State: {1}", key, mode.ToString())); } /// /// Clears all external sources on the codec /// public void ClearExternalSources() { - SendText("xCommand UserInterface Presentation ExternalSource RemoveAll"); + EnqueueCommand("xCommand UserInterface Presentation ExternalSource RemoveAll"); } @@ -2338,7 +2356,7 @@ ConnectorID: {2}" /// public void SetSelectedSource(string key) { - SendText(string.Format("xCommand UserInterface Presentation ExternalSource Select SourceIdentifier: {0}", key)); + EnqueueCommand(string.Format("xCommand UserInterface Presentation ExternalSource Select SourceIdentifier: {0}", key)); _externalSourceChangeRequested = true; } @@ -2377,7 +2395,7 @@ ConnectorID: {2}" /// public void CameraMuteOn() { - SendText("xCommand Video Input MainVideo Mute"); + EnqueueCommand("xCommand Video Input MainVideo Mute"); } /// @@ -2385,7 +2403,7 @@ ConnectorID: {2}" /// public void CameraMuteOff() { - SendText("xCommand Video Input MainVideo Unmute"); + EnqueueCommand("xCommand Video Input MainVideo Unmute"); } /// @@ -2405,12 +2423,12 @@ ConnectorID: {2}" public void ActivateDoNotDisturbMode() { - SendText("xCommand Conference DoNotDisturb Activate"); + EnqueueCommand("xCommand Conference DoNotDisturb Activate"); } public void DeactivateDoNotDisturbMode() { - SendText("xCommand Conference DoNotDisturb Deactivate"); + EnqueueCommand("xCommand Conference DoNotDisturb Deactivate"); } public void ToggleDoNotDisturbMode() @@ -2435,7 +2453,7 @@ ConnectorID: {2}" public void HalfwakeActivate() { - SendText("xCommand Standby Halfwake"); + EnqueueCommand("xCommand Standby Halfwake"); } #endregion @@ -2463,8 +2481,10 @@ ConnectorID: {2}" public class CodecSyncState : IKeyed { bool _InitialSyncComplete; + private readonly CiscoSparkCodec _parent; public event EventHandler InitialSyncCompleted; + private readonly CrestronQueue _commandQueue; public string Key { get; private set; } @@ -2491,10 +2511,43 @@ ConnectorID: {2}" public bool FeedbackWasRegistered { get; private set; } - public CodecSyncState(string key) + public CodecSyncState(string key, CiscoSparkCodec parent) { Key = key; + _parent = parent; + _commandQueue = new CrestronQueue(25); CodecDisconnected(); + + + while (InitialSyncComplete && !_commandQueue.IsEmpty) + { + var query = _commandQueue.Dequeue(); + + _parent.SendText(query); + } + } + + //public void StartSync() + //{ + // DequeueQueries(); + //} + + //private void DequeueQueries() + //{ + + // while (!_commandQueue.IsEmpty) + // { + // var query = _commandQueue.Dequeue(); + + // _parent.SendText(query); + // } + + // InitialQueryMessagesSent(); + //} + + public void AddCommandToQueue(string query) + { + _commandQueue.Enqueue(query); } public void LoginMessageReceived() @@ -2527,6 +2580,7 @@ ConnectorID: {2}" public void CodecDisconnected() { + _commandQueue.Clear(); LoginMessageWasReceived = false; InitialConfigurationMessageWasReceived = false; InitialStatusMessageWasReceived = false; @@ -2536,7 +2590,7 @@ ConnectorID: {2}" void CheckSyncStatus() { - if (LoginMessageWasReceived && InitialConfigurationMessageWasReceived && InitialStatusMessageWasReceived && FeedbackWasRegistered) + if (LoginMessageWasReceived && InitialConfigurationMessageWasReceived && InitialStatusMessageWasReceived && FeedbackWasRegistered) { InitialSyncComplete = true; Debug.Console(1, this, "Initial Codec Sync Complete!"); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index a43ea79c..1fa58ffb 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -3200,7 +3200,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom CheckSyncStatus(); } - public void InitialQueryMessagesSent() + private void InitialQueryMessagesSent() { InitialQueryMessagesWereSent = true; Debug.Console(1, this, "Query Messages Sent."); From 6df594dd7fe21d93c2f8c3764ad3b090b807e60e Mon Sep 17 00:00:00 2001 From: Jonathan Arndt Date: Mon, 14 Feb 2022 17:21:15 -0800 Subject: [PATCH 051/202] Updates to CiscoSparkCodec queue --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 75 ++++++++++--------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index b6f59dac..1a9dec0e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -359,7 +359,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } else { - CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, "xStatus SystemUnit Software Version\r"); + CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, "xStatus SystemUnit Software Version\r\n"); } if (props.Sharing != null) @@ -662,6 +662,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { var cameraInfo = new List(); + Debug.Console(0, this, "Codec reports {0} cameras", CodecStatus.Status.Cameras.Camera.Count); + foreach (var camera in CodecStatus.Status.Cameras.Camera) { Debug.Console(0, this, @@ -766,12 +768,12 @@ ConnectorID: {2}" if (CommDebuggingIsOn) { if (!_jsonFeedbackMessageIsIncoming) - Debug.Console(1, this, "RX: '{0}'", args.Text); + Debug.Console(1, this, "RX: '{0}'", ComTextHelper.GetDebugText(args.Text)); } - if(args.Text.Contains("xCommand")) + if(args.Text.ToLower().Contains("xcommand")) { - Debug.Console(2, this, "Received command echo response. Ignoring"); + Debug.Console(1, this, "Received command echo response. Ignoring"); return; } @@ -819,12 +821,17 @@ ConnectorID: {2}" if(_loginMessageReceivedTimer != null) _loginMessageReceivedTimer.Stop(); - SendText("echo off"); + //SendText("echo off"); SendText("xPreferences outputmode json"); break; } case "xpreferences outputmode json": { + if (_syncState.JsonResponseModeSet) + return; + + _syncState.JsonResponseModeMessageReceived(); + if (!_syncState.InitialStatusMessageWasReceived) SendText("xStatus"); break; @@ -844,7 +851,7 @@ ConnectorID: {2}" /// public void EnqueueCommand(string command) { - _syncState.AddCommandToQueue(command + Delimiter); + _syncState.AddCommandToQueue(command); } /// @@ -856,7 +863,7 @@ ConnectorID: {2}" public void SendText(string command) { if (CommDebuggingIsOn) - Debug.Console(1, this, "Sending: '{0}'", command); + Debug.Console(1, this, "Sending: '{0}'", ComTextHelper.GetDebugText(command + Delimiter)); Communication.SendText(command + Delimiter); } @@ -2002,9 +2009,6 @@ ConnectorID: {2}" var camCount = CodecStatus.Status.Cameras.Camera.Count; - Debug.Console(0, this, "Codec reports {0} cameras", camCount); - - // Deal with the case of 1 or no reported cameras if (camCount <= 1) { @@ -2505,6 +2509,8 @@ ConnectorID: {2}" public bool LoginMessageWasReceived { get; private set; } + public bool JsonResponseModeSet { get; private set; } + public bool InitialStatusMessageWasReceived { get; private set; } public bool InitialConfigurationMessageWasReceived { get; private set; } @@ -2515,35 +2521,22 @@ ConnectorID: {2}" { Key = key; _parent = parent; - _commandQueue = new CrestronQueue(25); + _commandQueue = new CrestronQueue(50); CodecDisconnected(); - - - while (InitialSyncComplete && !_commandQueue.IsEmpty) - { - var query = _commandQueue.Dequeue(); - - _parent.SendText(query); - } } - //public void StartSync() - //{ - // DequeueQueries(); - //} + private void ProcessQueuedCommands() + { + while (InitialSyncComplete) + { + if (!_commandQueue.IsEmpty) + { + var query = _commandQueue.Dequeue(); - //private void DequeueQueries() - //{ - - // while (!_commandQueue.IsEmpty) - // { - // var query = _commandQueue.Dequeue(); - - // _parent.SendText(query); - // } - - // InitialQueryMessagesSent(); - //} + _parent.SendText(query); + } + } + } public void AddCommandToQueue(string query) { @@ -2557,6 +2550,13 @@ ConnectorID: {2}" CheckSyncStatus(); } + public void JsonResponseModeMessageReceived() + { + JsonResponseModeSet = true; + Debug.Console(1, this, "Json Response Mode Message Received."); + CheckSyncStatus(); + } + public void InitialStatusMessageReceived() { InitialStatusMessageWasReceived = true; @@ -2582,6 +2582,7 @@ ConnectorID: {2}" { _commandQueue.Clear(); LoginMessageWasReceived = false; + JsonResponseModeSet = false; InitialConfigurationMessageWasReceived = false; InitialStatusMessageWasReceived = false; FeedbackWasRegistered = false; @@ -2590,10 +2591,12 @@ ConnectorID: {2}" void CheckSyncStatus() { - if (LoginMessageWasReceived && InitialConfigurationMessageWasReceived && InitialStatusMessageWasReceived && FeedbackWasRegistered) + if (LoginMessageWasReceived && JsonResponseModeSet && InitialConfigurationMessageWasReceived && InitialStatusMessageWasReceived && FeedbackWasRegistered) { InitialSyncComplete = true; Debug.Console(1, this, "Initial Codec Sync Complete!"); + Debug.Console(1, this, "{0} Command queued. Processing now...", _commandQueue.Count); + ProcessQueuedCommands(); } else InitialSyncComplete = false; From 80b5fb6c7f1090a6c095e6418c491faa338fcf5a Mon Sep 17 00:00:00 2001 From: Jonathan Arndt Date: Tue, 15 Feb 2022 11:27:37 -0800 Subject: [PATCH 052/202] CiscoSparkCodec > Removed inner IF of processQueuedCommands and added CrestronInvoke to CheckSyncStatus --- .../PepperDashEssentialsBase/Queues/GenericQueue.cs | 2 +- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs index a1cef30d..8dca9803 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs @@ -118,7 +118,7 @@ namespace PepperDash.Essentials.Core.Queues /// public GenericQueue(string key, int pacing, Thread.eThreadPriority priority, int capacity) : this(key, priority, capacity, pacing) - { + { } /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 1a9dec0e..edcc61ec 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -2529,12 +2529,9 @@ ConnectorID: {2}" { while (InitialSyncComplete) { - if (!_commandQueue.IsEmpty) - { - var query = _commandQueue.Dequeue(); + var query = _commandQueue.Dequeue(); - _parent.SendText(query); - } + _parent.SendText(query); } } @@ -2596,7 +2593,11 @@ ConnectorID: {2}" InitialSyncComplete = true; Debug.Console(1, this, "Initial Codec Sync Complete!"); Debug.Console(1, this, "{0} Command queued. Processing now...", _commandQueue.Count); - ProcessQueuedCommands(); + + // Invoke a thread for the queue + CrestronInvoke.BeginInvoke((o) => { + ProcessQueuedCommands(); + }); } else InitialSyncComplete = false; From a06652ee61345df7726b4338a74e460d18361758 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 21 Feb 2022 12:06:09 -0700 Subject: [PATCH 053/202] chore(essentials): Cleans up some debug statements no longer needed --- .../EssentialsHuddleVtc1PanelAvFunctionsDriver.cs | 8 ++++---- PepperDashEssentials/UIDrivers/JoinedSigInterlock.cs | 10 +++++----- .../UIDrivers/ScreenSaverController.cs | 12 ++++++------ .../VideoCodec/ZoomRoom/ZoomRoom.cs | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 44091362..80fb0ba8 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -493,10 +493,10 @@ namespace PepperDash.Essentials // and the LastMeetingDismissed != this meeting var lastMeetingDismissed = meetings.FirstOrDefault(m => m.Id == LastMeetingDismissedId); - Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*", - CurrentRoom.OnFeedback.BoolValue, - LastMeetingDismissedId, - lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToString("t", Global.Culture) : ""); + //Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*", + // CurrentRoom.OnFeedback.BoolValue, + // LastMeetingDismissedId, + // lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToString("t", Global.Culture) : ""); var meeting = meetings.LastOrDefault(m => m.Joinable); if (CurrentRoom.OnFeedback.BoolValue diff --git a/PepperDashEssentials/UIDrivers/JoinedSigInterlock.cs b/PepperDashEssentials/UIDrivers/JoinedSigInterlock.cs index 04e01eb0..a7dba246 100644 --- a/PepperDashEssentials/UIDrivers/JoinedSigInterlock.cs +++ b/PepperDashEssentials/UIDrivers/JoinedSigInterlock.cs @@ -52,7 +52,7 @@ namespace PepperDash.Essentials { var prevJoin = CurrentJoin; var wasShown = _IsShown; - Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join); + //Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join); if (CurrentJoin == join && TriList.BooleanInput[join].BoolValue) return; SetButDontShow(join); @@ -71,7 +71,7 @@ namespace PepperDash.Essentials var prevJoin = CurrentJoin; var wasShown = IsShown; - Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join); + //Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join); if (CurrentJoin == join) HideAndClear(); else @@ -92,7 +92,7 @@ namespace PepperDash.Essentials { var prevJoin = CurrentJoin; var wasShown = IsShown; - Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin); + //Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin); Hide(); CurrentJoin = 0; @@ -108,7 +108,7 @@ namespace PepperDash.Essentials var prevJoin = CurrentJoin; var wasShown = IsShown; - Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin); + //Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin); if (CurrentJoin > 0) { TriList.BooleanInput[CurrentJoin].BoolValue = false; @@ -125,7 +125,7 @@ namespace PepperDash.Essentials var prevJoin = CurrentJoin; var wasShown = IsShown; - Debug.Console(2, "Trilist {0:X2}, interlock showing {1}", TriList.ID, CurrentJoin); + //Debug.Console(2, "Trilist {0:X2}, interlock showing {1}", TriList.ID, CurrentJoin); if (CurrentJoin > 0) { TriList.BooleanInput[CurrentJoin].BoolValue = true; diff --git a/PepperDashEssentials/UIDrivers/ScreenSaverController.cs b/PepperDashEssentials/UIDrivers/ScreenSaverController.cs index 0f75e2a2..11ce587a 100644 --- a/PepperDashEssentials/UIDrivers/ScreenSaverController.cs +++ b/PepperDashEssentials/UIDrivers/ScreenSaverController.cs @@ -51,7 +51,7 @@ namespace PepperDash.Essentials 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) { @@ -67,11 +67,11 @@ namespace PepperDash.Essentials 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) { - Debug.Console(2, "Stopping PositionTimer: {0:X2}", TriList.ID); + //Debug.Console(2, "Stopping PositionTimer: {0:X2}", TriList.ID); PositionTimer.Stop(); PositionTimer.Dispose(); PositionTimer = null; @@ -89,7 +89,7 @@ namespace PepperDash.Essentials 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) { @@ -122,7 +122,7 @@ namespace PepperDash.Essentials 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() { - Debug.Console(2, "Hiding all screensaver positions: {0:X2}", TriList.ID); + //Debug.Console(2, "Hiding all screensaver positions: {0:X2}", TriList.ID); PositionInterlock.HideAndClear(); } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 6ea90c80..e2c06eee 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -33,14 +33,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public uint DefaultMeetingDurationMin { get; private set; } /// - /// CR LF + /// CR LF CR LF Delimits an echoed response to a command /// private const string EchoDelimiter = "\x0D\x0A\x0D\x0A"; private const string SendDelimiter = "\x0D"; /// - /// CR LF } CR LF + /// CR LF } CR LF Delimits a JSON response /// private const string JsonDelimiter = "\x0D\x0A\x7D\x0D\x0A"; From 55ab593d7379ff437f8bb1d07dc78f98d3ac6892 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 24 Feb 2022 14:34:38 -0700 Subject: [PATCH 054/202] feat(essentails): #911 swaps cisco comm monitor poll string --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index edcc61ec..c9e584d3 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -359,7 +359,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } 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) From b3f75684695db0174781e422b4ca211f81e1c4d0 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 24 Feb 2022 22:03:03 -0700 Subject: [PATCH 055/202] fix(essentials): updates to IHasDirectory and ZoomRoom Prevents serialization of CurrentDirectoryResults object. Modified OnDirectoryResultsReturne helper method for ZoomRoom to fix stripping of contacts --- .../Codec/iHasDirectory.cs | 3 +- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 48 +++++++++---------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs index 642f03d0..57dbbd6b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs @@ -65,8 +65,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec { /// /// 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 /// - [JsonProperty("directoryResults")] + [JsonIgnore] public List CurrentDirectoryResults { get; private set; } [JsonProperty("contacts")] diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index e2c06eee..ffab3ea5 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -400,10 +400,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { _currentDirectoryResult = value; - Debug.Console(2, this, "CurrentDirectoryResult Updated. ResultsFolderId: {0}", - _currentDirectoryResult.ResultsFolderId); - - CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); + Debug.Console(2, this, "CurrentDirectoryResult Updated. ResultsFolderId: {0} Contact Count: {1}", + _currentDirectoryResult.ResultsFolderId, _currentDirectoryResult.CurrentDirectoryResults.Count); OnDirectoryResultReturned(_currentDirectoryResult); } @@ -1305,6 +1303,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // This result will always be the complete contents of the directory and never // A subset of the results via a search + // Clear out any existing data + Status.Phonebook = new zStatus.Phonebook(); + JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); var directoryResults = @@ -1318,10 +1319,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); } - if (directoryResults.ResultsFolderId != "root") - { - directoryResults.ResultsFolderId = "root"; - } + directoryResults.ResultsFolderId = "root"; DirectoryRoot = directoryResults; @@ -2696,27 +2694,27 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { try { - Debug.Console(2, this, "OnDirectoryResultReturned"); + Debug.Console(2, this, "OnDirectoryResultReturned. Result has {0} contacts", result.Contacts.Count); - var directoryResult = new CodecDirectory(); + var directoryResult = result; // If result is Root, create a copy and filter out contacts whose parent folder is not root - if (!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue) - { - Debug.Console(2, this, "Filtering DirectoryRoot to remove contacts for display"); + //if (!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue) + //{ + // Debug.Console(2, this, "Filtering DirectoryRoot to remove contacts for display"); - directoryResult.ResultsFolderId = result.ResultsFolderId; - directoryResult.AddFoldersToDirectory(result.Folders); - directoryResult.AddContactsToDirectory( - result.Contacts.Where((c) => c.ParentFolderId == result.ResultsFolderId).ToList()); - } - else - { - directoryResult = result; - } + // directoryResult.ResultsFolderId = result.ResultsFolderId; + // directoryResult.AddFoldersToDirectory(result.Folders); + // directoryResult.AddContactsToDirectory( + // result.Contacts.Where((c) => c.ParentFolderId == result.ResultsFolderId).ToList()); + //} + //else + //{ + // directoryResult = result; + //} - Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0}", - !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); + Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0} Contact Count: {1}", + !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue, directoryResult.Contacts.Count); // This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology var handler = DirectoryResultReturned; @@ -2728,6 +2726,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue }); } + + CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); } catch (Exception e) { From 06fdee313a55f5e6415715a94ea08cb68c856fed Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 25 Feb 2022 21:10:44 -0700 Subject: [PATCH 056/202] fix(essentials): adds missing property decorators and unmutes video on camera select --- .../Essentials Devices Common/Cameras/CameraBase.cs | 8 +++++--- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 5 +++++ .../VideoCodec/ZoomRoom/ZoomRoomCamera.cs | 5 ++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs index 18a1ad36..1ef679ba 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs @@ -29,6 +29,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs { + [JsonProperty("controlMode", NullValueHandling = NullValueHandling.Ignore)] public eCameraControlMode ControlMode { get; protected set; } #region IRoutingOutputs Members @@ -37,6 +38,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras #endregion + [JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)] public bool CanPan { get @@ -44,7 +46,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras return (Capabilities & eCameraCapabilities.Pan) == eCameraCapabilities.Pan; } } - + [JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)] public bool CanTilt { get @@ -52,7 +54,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras return (Capabilities & eCameraCapabilities.Tilt) == eCameraCapabilities.Tilt; } } - + [JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)] public bool CanZoom { get @@ -60,7 +62,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras return (Capabilities & eCameraCapabilities.Zoom) == eCameraCapabilities.Zoom; } } - + [JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)] public bool CanFocus { get diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index ffab3ea5..7542594d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -342,6 +342,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { Debug.Console(1, this, "Selected Camera with key: '{0}'", camera.Key); SelectedCamera = camera; + + if (CameraIsMutedFeedback.BoolValue) + { + CameraMuteOff(); + } } else { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs index b0fc52fe..4b723ec8 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomCamera.cs @@ -7,6 +7,8 @@ using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Devices.Common.Cameras; +using Newtonsoft.Json; + namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { public enum eZoomRoomCameraState @@ -34,7 +36,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { protected ZoomRoom ParentCodec { get; private set; } - public int Id = 0; // ID of near end selected camara is always 0 + [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] + public int? Id = 0; // ID of near end selected camara is always 0 private int ContinueTime = 10; // number of milliseconds between issuing continue commands From 97b9ed5016f9855cd4b0b03f2cd2e19d2244c9f3 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 28 Feb 2022 19:21:27 -0700 Subject: [PATCH 057/202] fix(essentials): Fixes SetupCameras to not add duplicate cameras to the list --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 7542594d..f21d2068 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -1844,6 +1844,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } case "video camera line": { + Status.Cameras.Clear(); + JsonConvert.PopulateObject(responseObj.ToString(), Status.Cameras); if (!_syncState.CamerasHaveBeenSetUp) @@ -2763,14 +2765,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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) - { - SelectedCamera = camera; - } + Cameras.Add(camera); + + if (cam.Selected) + { + SelectedCamera = camera; + } + } } if (IsInCall) From 787c8eb954f616a7553a4ad435df5f779140eab5 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 1 Mar 2022 21:43:38 -0700 Subject: [PATCH 058/202] feat(essentials): Adds new interface and event to notify if video unmute is requested --- .../Cameras/CameraControl.cs | 5 +++++ .../VideoCodec/ZoomRoom/ZoomRoom.cs | 12 ++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs index 208b38de..cbf53476 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs @@ -57,6 +57,11 @@ namespace PepperDash.Essentials.Devices.Common.Cameras void CameraMuteToggle(); } + public interface IHasCameraMuteWithUnmuteReqeust : IHasCameraMute + { + event EventHandler VideoUnmuteRequested; + } + public class CameraSelectedEventArgs : EventArgs { public CameraBase SelectedCamera { get; private set; } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index f21d2068..ee3cdc0f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -24,11 +24,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, IRouting, - IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, + IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMuteWithUnmuteReqeust, IHasCameraAutoMode, IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting, IHasMeetingLock, IHasMeetingRecording { + public event EventHandler VideoUnmuteRequested; + private const long MeetingRefreshTimer = 60000; public uint DefaultMeetingDurationMin { get; private set; } @@ -1611,7 +1613,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } case "videounmuterequest": { - // TODO: notify room of a request to unmute video + var handler = VideoUnmuteRequested; + + if (handler != null) + { + handler(this, null); + } + break; } case "meetingneedspassword": From 89dd098ea6ca995861fdc4a0015f5d6fce3a93c0 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 3 Mar 2022 14:39:54 -0700 Subject: [PATCH 059/202] feat(essentials): #912 Updates to GenericCommunicationMonitor to better monitor socket status --- .../Monitoring/GenericCommunicationMonitor.cs | 154 +++++++++++++++--- .../Display/SamsungMDCDisplay.cs | 2 +- 2 files changed, 131 insertions(+), 25 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Monitoring/GenericCommunicationMonitor.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Monitoring/GenericCommunicationMonitor.cs index 0d19762f..edb4c31b 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Monitoring/GenericCommunicationMonitor.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Monitoring/GenericCommunicationMonitor.cs @@ -16,11 +16,28 @@ namespace PepperDash.Essentials.Core /// /// Used for monitoring comms that are IBasicCommunication. Will send a poll string and provide an event when /// statuses change. + /// Default monitoring uses TextReceived event on Client. /// public class GenericCommunicationMonitor : StatusMonitorBase { public IBasicCommunication Client { get; private set; } + /// + /// Will monitor Client.BytesReceived if set to true. Otherwise the default is to monitor Client.TextReceived + /// + public bool MonitorBytesReceived { get; private set; } + + /// + /// Return true if the Client is ISocketStatus + /// + public bool IsSocket + { + get + { + return Client is ISocketStatus; + } + } + long PollTime; CTimer PollTimer; string PollString; @@ -46,8 +63,20 @@ namespace PepperDash.Essentials.Core Client = client; PollTime = pollTime; PollString = pollString; + + if (IsSocket) + { + (Client as ISocketStatus).ConnectionChange += new EventHandler(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); + } + /// /// Poll is a provided action instead of string /// @@ -69,6 +98,19 @@ namespace PepperDash.Essentials.Core Client = client; PollTime = pollTime; PollAction = pollAction; + + if (IsSocket) + { + (Client as ISocketStatus).ConnectionChange += new EventHandler(socket_ConnectionChange); + } + + } + + public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, + long warningTime, long errorTime, Action pollAction, bool monitorBytesReceived) : + this(parent, client, pollTime, warningTime, errorTime, pollAction) + { + SetMonitorBytesReceived(monitorBytesReceived); } @@ -79,23 +121,96 @@ namespace PepperDash.Essentials.Core CommunicationMonitorConfig props) : this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString) { + if (IsSocket) + { + (Client as ISocketStatus).ConnectionChange += new EventHandler(socket_ConnectionChange); + } } + /// + /// Builds the monitor from a config object and takes a bool to specify whether to monitor BytesReceived + /// Default is to monitor TextReceived + /// + /// + /// + /// + /// + public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, CommunicationMonitorConfig props, bool monitorBytesReceived) : + this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString) + { + SetMonitorBytesReceived(monitorBytesReceived); + } + + void SetMonitorBytesReceived(bool monitorBytesReceived) + { + MonitorBytesReceived = monitorBytesReceived; + } + public override void Start() { - Client.BytesReceived += Client_BytesReceived; - Poll(); - PollTimer = new CTimer(o => Poll(), null, PollTime, PollTime); + if (MonitorBytesReceived) + { + Client.BytesReceived += Client_BytesReceived; + } + else + { + Client.TextReceived += Client_TextReceived; + } + + if (!IsSocket) + { + BeginPolling(); + } } + void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) + { + if (!e.Client.IsConnected) + { + // Immediately stop polling and notify that device is offline + Stop(); + Status = MonitorStatus.InError; + ResetErrorTimers(); + } + else + { + // Start polling and set status to unknow and let poll result update the status to IsOk when a response is received + Status = MonitorStatus.StatusUnknown; + Start(); + BeginPolling(); + } + } + + void BeginPolling() + { + Poll(); + PollTimer = new CTimer(o => Poll(), null, PollTime, PollTime); + } + public override void Stop() { - Client.BytesReceived -= this.Client_BytesReceived; - PollTimer.Stop(); - PollTimer = null; - StopErrorTimers(); + if(MonitorBytesReceived) + { + Client.BytesReceived -= this.Client_BytesReceived; + } + else + { + Client.TextReceived -= Client_TextReceived; + } + + if (PollTimer != null) + { + PollTimer.Stop(); + PollTimer = null; + StopErrorTimers(); + } } + void Client_TextReceived(object sender, GenericCommMethodReceiveTextArgs e) + { + DataReceived(); + } + /// /// Upon any receipt of data, set everything to ok! /// @@ -103,10 +218,14 @@ namespace PepperDash.Essentials.Core /// void Client_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e) { - Status = MonitorStatus.IsOk; - ResetErrorTimers(); - // - } + DataReceived(); + } + + void DataReceived() + { + Status = MonitorStatus.IsOk; + ResetErrorTimers(); + } void Poll() { @@ -124,19 +243,6 @@ namespace PepperDash.Essentials.Core Debug.Console(2, this, "Comm not connected"); } } - - /// - /// When the client connects, and we're waiting for it, respond and disconect from event - /// - void OneTimeConnectHandler(object o, EventArgs a) - { - if (Client.IsConnected) - { - //Client.IsConnected -= OneTimeConnectHandler; - Debug.Console(2, this, "Comm connected"); - Poll(); - } - } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs index 65e38408..9fcb7295 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs @@ -99,7 +99,7 @@ namespace PepperDash.Essentials.Devices.Displays WarmupTime = 10000; CooldownTime = 8000; - CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 2000, 120000, 300000, StatusGet); + CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 2000, 120000, 300000, StatusGet, true); DeviceManager.AddDevice(CommunicationMonitor); VolumeIncrementer = new ActionIncrementer(655, 0, 65535, 800, 80, From 5f668c717374ab9709a6f8006ec82f9c5febe2df Mon Sep 17 00:00:00 2001 From: Michael Willis Date: Tue, 8 Mar 2022 09:42:53 -0700 Subject: [PATCH 060/202] Typo in RoutingPort Constructor - isInternal --- .../PepperDashEssentialsBase/Routing/RoutingPort.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs index cfd6f09e..79dd4eda 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs @@ -25,7 +25,7 @@ namespace PepperDash.Essentials.Core Type = type; ConnectionType = connType; Selector = selector; - IsInternal = IsInternal; + IsInternal = isInternal; } } From b23b7cb81385aa39d5efbf2b6b3d5dce138232f1 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 29 Mar 2022 12:49:49 -0600 Subject: [PATCH 061/202] fix(essentials): #927 moves SetUpRouting() to constructor --- .../Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index ee3cdc0f..52df311c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -170,6 +170,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom MeetingIsLockedFeedback = new BoolFeedback(() => Configuration.Call.Lock.Enable ); MeetingIsRecordingFeedback = new BoolFeedback(() => Status.Call.CallRecordInfo.meetingIsBeingRecorded ); + + SetUpRouting(); } public CommunicationGather PortGather { get; private set; } @@ -489,8 +491,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void SyncState_InitialSyncCompleted(object sender, EventArgs e) { - SetUpRouting(); - SetIsReady(); } From 832102f4bb8dea2dc01a555e9d9eb31a1687b3cb Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 29 Mar 2022 16:02:59 -0500 Subject: [PATCH 062/202] feat: updated ExecuteSwitch to turn the display power on if _PowerIsOn is false --- .../PepperDashEssentialsBase/Display/MockDisplay.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs index eb529376..4ac61943 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs @@ -111,7 +111,12 @@ namespace PepperDash.Essentials.Core public override void ExecuteSwitch(object selector) { - Debug.Console(2, this, "ExecuteSwitch: {0}", selector); + Debug.Console(2, this, "ExecuteSwitch: {0}", selector); + + if (!_PowerIsOn) + { + PowerOn(); + } } From e2b8e356ff36cc54b09527c039152fb9bcff9940 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 29 Mar 2022 16:03:46 -0500 Subject: [PATCH 063/202] fix: Updated ZoomRoom constructor to build HdmiOutput1,2,3 --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 52df311c..c40b577d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -113,14 +113,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this); - Output1 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, + Output1 = new RoutingOutputPort(RoutingPortNames.HdmiOut1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, null, this); - Output2 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, + Output2 = new RoutingOutputPort(RoutingPortNames.HdmiOut2, eRoutingSignalType.Video, eRoutingPortConnectionType.DisplayPort, null, this); + Output3 = new RoutingOutputPort(RoutingPortNames.HdmiOut3, + eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, null, this); + SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc); CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc); @@ -301,6 +305,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public RoutingInputPort CodecOsdIn { get; private set; } public RoutingOutputPort Output1 { get; private set; } public RoutingOutputPort Output2 { get; private set; } + public RoutingOutputPort Output3 { get; private set; } #region ICommunicationMonitor Members From 309605ee3886857fa73cad7af5da918a36ceba33 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 29 Mar 2022 16:04:14 -0500 Subject: [PATCH 064/202] fix: updated packages.config to reference PepperDash Core 1.1.1, previously referencing RC build --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index 41f858a6..4c411add 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From 1abe54fa4829dc35bdf3e241e52b48d488173edf Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 26 Apr 2022 15:32:34 -0500 Subject: [PATCH 065/202] fix: removed duplicate PasswordRequired event handler from LinkZoomRoomToApi method --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index ee3cdc0f..058bcdd9 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2429,29 +2429,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom }); 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) => { From 82ac34d3b695edf3c85c9f3a4b2bd3c6931c53f9 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 17 May 2022 11:26:19 -0600 Subject: [PATCH 066/202] fix(essentials): Updates Status.Call subscription mechanism to persist properly Makes sure all subscriptions are un and resubscribed whenever Status.Call is constructed --- .../VideoCodec/Interfaces/IHasMeetingInfo.cs | 5 +- .../Interfaces/IHasMeetingRecording.cs | 5 + .../VideoCodec/ZoomRoom/ResponseObjects.cs | 20 ++- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 152 +++++++++++------- 4 files changed, 116 insertions(+), 66 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs index 0d304028..d6d6924d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs @@ -42,9 +42,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces public Boolean WaitingForHost { get; private set; } [JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)] public Boolean IsLocked { get; private set; } + [JsonProperty("isBeingRecorded", NullValueHandling = NullValueHandling.Ignore)] + public Boolean IsBeingRecorded { 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 isBeingRecorded) { Id = id; Name = name; @@ -55,6 +57,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces IsSharingMeeting = isSharingMeeting; WaitingForHost = waitingForHost; IsLocked = isLocked; + IsBeingRecorded = isBeingRecorded; } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingRecording.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingRecording.cs index 771a0865..8aded9bf 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingRecording.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingRecording.cs @@ -15,4 +15,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces void StopRecording(); void ToggleRecording(); } + + public interface IHasMeetingRecordingWithPrompt : IHasMeetingRecording + { + BoolFeedback RecordConsentPromptIsVisible { get; } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index f6355d63..b5296410 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -31,10 +31,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom protected void NotifyPropertyChanged(string propertyName) { - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); - } + var handler = PropertyChanged; + if (handler != null) + { + handler(this, new PropertyChangedEventArgs(propertyName)); + } + else + { + Debug.Console(2, "PropertyChanged event is NULL"); + } } #endregion @@ -778,13 +783,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } set { + //Debug.Console(2, "************************************setting value of meetingIsBeingRecorded to: {0}", value); if (value != _meetingIsBeingRecorded) { _meetingIsBeingRecorded = value; + //Debug.Console(2, "********************************set value of meetingIsBeingRecorded to: {0}", _meetingIsBeingRecorded); NotifyPropertyChanged("meetingIsBeingRecorded"); } } } + + public CallRecordInfo() + { + Debug.Console(2, Debug.ErrorLogLevel.Notice, "********************************************* CallRecordInfo() ******************************************"); + } } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index d32934e2..bb50b06a 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -27,7 +27,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMuteWithUnmuteReqeust, IHasCameraAutoMode, IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting, - IHasMeetingLock, IHasMeetingRecording + IHasMeetingLock, IHasMeetingRecordingWithPrompt { public event EventHandler VideoUnmuteRequested; @@ -175,6 +175,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom MeetingIsRecordingFeedback = new BoolFeedback(() => Status.Call.CallRecordInfo.meetingIsBeingRecorded ); + RecordConsentPromptIsVisible = new BoolFeedback(() => _recordConsentPromptIsVisible); + SetUpRouting(); } @@ -499,20 +501,66 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom SetIsReady(); } + /// + /// Handles subscriptions to Status.Call and sub objects. Needs to be called whenever Status.Call is constructed + /// private void SetUpCallFeedbackActions() { - Status.Call.Sharing.PropertyChanged += HandleSharingStateUpdate; + Status.Call.Sharing.PropertyChanged -= HandleSharingStateUpdate; + Status.Call.Sharing.PropertyChanged += HandleSharingStateUpdate; - Status.Call.PropertyChanged += (o, a) => - { - if (a.PropertyName == "Info") - { - Debug.Console(1, this, "Updating Call Status"); - UpdateCallStatus(); - } - }; + Status.Call.PropertyChanged -= HandleCallStateUpdate; + Status.Call.PropertyChanged += HandleCallStateUpdate; + + Status.Call.CallRecordInfo.PropertyChanged -= HandleCallRecordInfoStateUpdate; + Status.Call.CallRecordInfo.PropertyChanged += HandleCallRecordInfoStateUpdate; } + private void HandleCallRecordInfoStateUpdate(object sender, PropertyChangedEventArgs a) + { + //Debug.Console(2, this, "**************** Status.Call.CallRecordInfo.PropertyChanged. PropertyName: {0} *********************************", a.PropertyName); + if (a.PropertyName == "meetingIsBeingRecorded") + { + //Debug.Console(2, this, "**************** Meeting Recording Info Updated. Recording: {0} **********************************", Status.Call.CallRecordInfo.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; + } + //else + //{ + // Debug.Console(2, this, "**************** Meeting Recording Info Updated. PropertyName: {0} *********************************", a.PropertyName); + //} + } + + 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) { if (a.PropertyName != "State") @@ -530,19 +578,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { var sharingStatus = GetSharingStatus(); - MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue); + MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue); return; } 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; } catch (Exception e) { Debug.Console(1, this, "Error processing state property update. {0}", e.Message); 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); } } @@ -551,6 +599,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// private void SetUpFeedbackActions() { + // Set these up initially. + SetUpCallFeedbackActions(); + Configuration.Audio.Output.PropertyChanged += (o, a) => { if (a.PropertyName == "Volume") @@ -645,7 +696,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom MeetingInfo.IsHost, MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, - MeetingIsLockedFeedback.BoolValue + MeetingIsLockedFeedback.BoolValue, + MeetingIsRecordingFeedback.BoolValue ); } }; @@ -678,41 +730,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) => { @@ -744,7 +761,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, - MeetingIsLockedFeedback.BoolValue); + MeetingIsLockedFeedback.BoolValue, + MeetingIsRecordingFeedback.BoolValue); MeetingInfo = meetingInfo; break; } @@ -1441,7 +1459,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, - MeetingIsLockedFeedback.BoolValue); + MeetingIsLockedFeedback.BoolValue, + MeetingIsRecordingFeedback.BoolValue); MeetingInfo = meetingInfo; PrintCurrentCallParticipants(); @@ -1656,14 +1675,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (MeetingInfo == null) { 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(); break; } 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(); @@ -1673,12 +1692,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (MeetingInfo == null) { 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; } 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; } @@ -1687,12 +1706,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // TODO: notify user that host has disabled unmuting video break; } - case "updatedcallrecordinfo": + case "updatecallrecordinfo": { JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.CallRecordInfo); break; } + case "recordingconsent": + { + _recordConsentPromptIsVisible = responseObj["isShow"].Value(); + RecordConsentPromptIsVisible.FireUpdate(); + break; + } case "phonecallstatus": { JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall); @@ -1762,7 +1787,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (result.Success) { - MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue); + MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue); break; } @@ -1963,12 +1988,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // If not crrently in a meeting, intialize the call object 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}; + // Resubscribe to all property change events after Status.Call is reconstructed + SetUpCallFeedbackActions(); OnCallStatusChange(new CodecActiveCallItem() {Status = eCodecCallStatus.Disconnected}); - - SetUpCallFeedbackActions(); } if (ActiveCalls.Count == 0) @@ -2108,7 +2132,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom GetIsHostMyself(), !String.Equals(Status.Call.Info.meeting_type,"NORMAL"), false, - MeetingIsLockedFeedback.BoolValue + MeetingIsLockedFeedback.BoolValue, + MeetingIsRecordingFeedback.BoolValue ); } // TODO [ ] Issue #868 @@ -2123,6 +2148,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom false, false, false, + false, false ); } @@ -3415,6 +3441,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public BoolFeedback MeetingIsRecordingFeedback { get; private set; } + bool _recordConsentPromptIsVisible; + + public BoolFeedback RecordConsentPromptIsVisible { get; private set; } + public void StartRecording() { SendText(string.Format("Command Call Record Enable: on")); From bdc4f0ae280d5e9ea84fd6ed2e0fedc62f4e8084 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 17 May 2022 13:20:53 -0600 Subject: [PATCH 067/202] fix(essentials): updates recording property name --- .../VideoCodec/Interfaces/IHasMeetingInfo.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs index d6d6924d..cfe70e1b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs @@ -42,11 +42,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces public Boolean WaitingForHost { get; private set; } [JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)] public Boolean IsLocked { get; private set; } - [JsonProperty("isBeingRecorded", NullValueHandling = NullValueHandling.Ignore)] - public Boolean IsBeingRecorded { 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, bool isBeingRecorded) + public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked, bool isRecording) { Id = id; Name = name; @@ -57,7 +57,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces IsSharingMeeting = isSharingMeeting; WaitingForHost = waitingForHost; IsLocked = isLocked; - IsBeingRecorded = isBeingRecorded; + IsRecording = isRecording; } } From 1e65c961c63811025cb88edefa6600057d1d0a06 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 17 May 2022 15:36:00 -0600 Subject: [PATCH 068/202] feat(essentials): Adds new interface capabilities * ability to admit a participant from waiting room * ability to acknowledge a meeting recording consent prompt --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 6198 ++++++++--------- .../Interfaces/IHasMeetingRecording.cs | 6 + .../VideoCodec/Interfaces/IHasParticipants.cs | 6 + .../VideoCodec/ZoomRoom/ZoomRoom.cs | 37 +- .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 72 +- 5 files changed, 3210 insertions(+), 3109 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 07c5c4bc..d1b383b0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -1,1150 +1,1150 @@ -using System; -using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.Bridges.JoinMaps -{ - public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced - { - #region Digital - - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete( - new JoinData - { - JoinNumber = 1, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Device is Online", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SendDtmfToSpecificCallIndex")] - public JoinDataComplete SendDtmfToSpecificCallIndex = new JoinDataComplete( - new JoinData - { - JoinNumber = 10, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "If High, will send DTMF tones to the call set by SelectCall analog. If low sends DTMF tones to last connected call.", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Dtmf1")] - public JoinDataComplete Dtmf1 = new JoinDataComplete( - new JoinData - { - JoinNumber = 11, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 1", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Dtmf2")] - public JoinDataComplete Dtmf2 = new JoinDataComplete( - new JoinData - { - JoinNumber = 12, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 2", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Dtmf3")] - public JoinDataComplete Dtmf3 = new JoinDataComplete( - new JoinData - { - JoinNumber = 13, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 3", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Dtmf4")] - public JoinDataComplete Dtmf4 = new JoinDataComplete( - new JoinData - { - JoinNumber = 14, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 4", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Dtmf5")] - public JoinDataComplete Dtmf5 = new JoinDataComplete( - new JoinData - { - JoinNumber = 15, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 5", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Dtmf6")] - public JoinDataComplete Dtmf6 = new JoinDataComplete( - new JoinData - { - JoinNumber = 16, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 6", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Dtmf7")] - public JoinDataComplete Dtmf7 = new JoinDataComplete( - new JoinData - { - JoinNumber = 17, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 7", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Dtmf8")] - public JoinDataComplete Dtmf8 = new JoinDataComplete( - new JoinData - { - JoinNumber = 18, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 8", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Dtmf9")] - public JoinDataComplete Dtmf9 = new JoinDataComplete( - new JoinData - { - JoinNumber = 19, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 9", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Dtmf0")] - public JoinDataComplete Dtmf0 = new JoinDataComplete( - new JoinData - { - JoinNumber = 20, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 0", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DtmfStar")] - public JoinDataComplete DtmfStar = new JoinDataComplete( - new JoinData - { - JoinNumber = 21, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF *", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DtmfPound")] - public JoinDataComplete DtmfPound = new JoinDataComplete( - new JoinData - { - JoinNumber = 22, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF #", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("EndAllCalls")] - public JoinDataComplete EndAllCalls = new JoinDataComplete( - new JoinData - { - JoinNumber = 24, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "End All Calls", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("HookState")] - public JoinDataComplete HookState = new JoinDataComplete( - new JoinData - { - JoinNumber = 31, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Current Hook State", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SpeedDialStart")] - public JoinDataComplete SpeedDialStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 41, - JoinSpan = 4 - }, - new JoinMetadata - { - Description = "Speed Dial", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingCall")] - public JoinDataComplete IncomingCall = new JoinDataComplete( - new JoinData - { - JoinNumber = 50, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Incoming Call", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingAnswer")] - public JoinDataComplete IncomingAnswer = new JoinDataComplete( - new JoinData - { - JoinNumber = 51, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Answer Incoming Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingReject")] - public JoinDataComplete IncomingReject = new JoinDataComplete( - new JoinData - { - JoinNumber = 52, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Reject Incoming Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ManualDial")] - public JoinDataComplete ManualDial = new JoinDataComplete( - new JoinData - { - JoinNumber = 71, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Dial manual string specified by CurrentDialString serial join", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialPhone")] - public JoinDataComplete DialPhone = new JoinDataComplete( - new JoinData - { - JoinNumber = 72, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Dial Phone", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("PhoneHookState")] - public JoinDataComplete PhoneHookState = new JoinDataComplete( - new JoinData - { - JoinNumber = 72, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Dial Phone", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("HangUpPhone")] - public JoinDataComplete HangUpPhone = new JoinDataComplete( - new JoinData - { - JoinNumber = 73, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Hang Up Phone", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("EndCallStart")] - public JoinDataComplete EndCallStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 81, - JoinSpan = 8 - }, - new JoinMetadata - { - Description = "End a specific call by call index. ", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("JoinAllCalls")] - public JoinDataComplete JoinAllCalls = new JoinDataComplete( - new JoinData - { - JoinNumber = 90, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Join all calls", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("JoinCallStart")] - public JoinDataComplete JoinCallStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 91, - JoinSpan = 8 - }, - new JoinMetadata - { - Description = "Join a specific call by call index. ", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectorySearchBusy")] - public JoinDataComplete DirectorySearchBusy = new JoinDataComplete( - new JoinData - { - JoinNumber = 100, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Search Busy FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryEntryIsContact")] - public JoinDataComplete DirectoryEntryIsContact = new JoinDataComplete( - new JoinData - { - JoinNumber = 101, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Selected Entry Is Contact FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryLineSelected")] - public JoinDataComplete DirectoryLineSelected = new JoinDataComplete( - new JoinData - { - JoinNumber = 101, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Line Selected FB", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryIsRoot")] - public JoinDataComplete DirectoryIsRoot = new JoinDataComplete( - new JoinData - { - JoinNumber = 102, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory is on Root FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryHasChanged")] - public JoinDataComplete DirectoryHasChanged = new JoinDataComplete( - new JoinData - { - JoinNumber = 103, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory has changed FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryRoot")] - public JoinDataComplete DirectoryRoot = new JoinDataComplete( - new JoinData - { - JoinNumber = 104, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Go to Directory Root", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryFolderBack")] - public JoinDataComplete DirectoryFolderBack = new JoinDataComplete( - new JoinData - { - JoinNumber = 105, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Go back one directory level", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryDialSelectedLine")] - public JoinDataComplete DirectoryDialSelectedLine = new JoinDataComplete( - new JoinData - { - JoinNumber = 106, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Dial selected directory line", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryDisableAutoDialSelectedLine")] - public JoinDataComplete DirectoryDisableAutoDialSelectedLine = new JoinDataComplete( - new JoinData - { - JoinNumber = 107, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Set high to disable automatic dialing of a contact when selected", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryDialSelectedContactMethod")] - public JoinDataComplete DirectoryDialSelectedContactMethod = new JoinDataComplete( - new JoinData - { - JoinNumber = 108, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to dial the selected contact method", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraTiltUp")] - public JoinDataComplete CameraTiltUp = new JoinDataComplete( - new JoinData - { - JoinNumber = 111, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Tilt Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraTiltDown")] - public JoinDataComplete CameraTiltDown = new JoinDataComplete( - new JoinData - { - JoinNumber = 112, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Tilt Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPanLeft")] - public JoinDataComplete CameraPanLeft = new JoinDataComplete( - new JoinData - { - JoinNumber = 113, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Pan Left", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPanRight")] - public JoinDataComplete CameraPanRight = new JoinDataComplete( - new JoinData - { - JoinNumber = 114, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Pan Right", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraZoomIn")] - public JoinDataComplete CameraZoomIn = new JoinDataComplete( - new JoinData - { - JoinNumber = 115, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Zoom In", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraZoomOut")] - public JoinDataComplete CameraZoomOut = new JoinDataComplete( - new JoinData - { - JoinNumber = 116, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Zoom Out", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraFocusNear")] - public JoinDataComplete CameraFocusNear = new JoinDataComplete( - new JoinData - { - JoinNumber = 117, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Focus Near", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraFocusFar")] - public JoinDataComplete CameraFocusFar = new JoinDataComplete( - new JoinData - { - JoinNumber = 118, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Focus Far", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraFocusAuto")] - public JoinDataComplete CameraFocusAuto = new JoinDataComplete( - new JoinData - { - JoinNumber = 119, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Auto Focus Trigger", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPresetSave")] - public JoinDataComplete CameraPresetSave = new JoinDataComplete( - new JoinData - { - JoinNumber = 121, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to save selected preset spcified by CameraPresetSelect analog join. FB will pulse for 3s when preset saved.", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeAuto")] - public JoinDataComplete CameraModeAuto = new JoinDataComplete( - new JoinData - { - JoinNumber = 131, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Mode Auto. Enables camera auto tracking mode, with feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeManual")] - public JoinDataComplete CameraModeManual = new JoinDataComplete( - new JoinData - { - JoinNumber = 132, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Mode Manual. Disables camera auto tracking mode, with feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeOff")] - public JoinDataComplete CameraModeOff = new JoinDataComplete( - new JoinData - { - JoinNumber = 133, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Mode Off. Disables camera video, with feedback. Works like video mute.", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSelfView")] - public JoinDataComplete CameraSelfView = new JoinDataComplete( - new JoinData - { - JoinNumber = 141, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Self View Toggle/FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraLayout")] - public JoinDataComplete CameraLayout = new JoinDataComplete( - new JoinData - { - JoinNumber = 142, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Layout Toggle", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSupportsAutoMode")] - public JoinDataComplete CameraSupportsAutoMode = new JoinDataComplete( - new JoinData - { - JoinNumber = 143, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Supports Auto Mode FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSupportsOffMode")] - public JoinDataComplete CameraSupportsOffMode = new JoinDataComplete( - new JoinData - { - JoinNumber = 144, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Supports Off Mode FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("UpdateMeetings")] - public JoinDataComplete UpdateMeetings = new JoinDataComplete( - new JoinData - { - JoinNumber = 160, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Update Meetings", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting1")] - public JoinDataComplete DialMeeting1 = new JoinDataComplete( - new JoinData - { - JoinNumber = 161, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Join first meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting2")] - public JoinDataComplete DialMeeting2 = new JoinDataComplete( - new JoinData - { - JoinNumber = 162, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Join second meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting3")] - public JoinDataComplete DialMeeting3 = new JoinDataComplete( - new JoinData - { - JoinNumber = 163, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Join third meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MicMuteOn")] - public JoinDataComplete MicMuteOn = new JoinDataComplete( - new JoinData - { - JoinNumber = 171, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Mic Mute On", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MicMuteOff")] - public JoinDataComplete MicMuteOff = new JoinDataComplete( - new JoinData - { - JoinNumber = 172, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Mic Mute Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MicMuteToggle")] - public JoinDataComplete MicMuteToggle = new JoinDataComplete( - new JoinData - { - JoinNumber = 173, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Mic Mute Toggle", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeUp")] - public JoinDataComplete VolumeUp = new JoinDataComplete( - new JoinData - { - JoinNumber = 174, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Volume Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeDown")] - public JoinDataComplete VolumeDown = new JoinDataComplete( - new JoinData - { - JoinNumber = 175, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Volume Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeMuteOn")] - public JoinDataComplete VolumeMuteOn = new JoinDataComplete( - new JoinData - { - JoinNumber = 176, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Volume Mute On", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeMuteOff")] - public JoinDataComplete VolumeMuteOff = new JoinDataComplete( - new JoinData - { - JoinNumber = 177, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Volume Mute Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeMuteToggle")] - public JoinDataComplete VolumeMuteToggle = new JoinDataComplete( - new JoinData - { - JoinNumber = 178, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Volume Mute Toggle", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("RemoveSelectedRecentCallItem")] - public JoinDataComplete RemoveSelectedRecentCallItem = new JoinDataComplete( - new JoinData - { - JoinNumber = 181, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to remove the selected recent call item specified by the SelectRecentCallItem analog join", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialSelectedRecentCallItem")] - public JoinDataComplete DialSelectedRecentCallItem = new JoinDataComplete( - new JoinData - { - JoinNumber = 182, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to dial the selected recent call item specified by the SelectRecentCallItem analog join", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceShareStart")] - public JoinDataComplete SourceShareStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 201, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Start Sharing & Feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceShareEnd")] - public JoinDataComplete SourceShareEnd = new JoinDataComplete( - new JoinData - { - JoinNumber = 202, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Stop Sharing & Feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("AutoShareWhileInCall")] - public JoinDataComplete SourceShareAutoStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 203, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "When high, will autostart sharing when a call is joined", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("RecievingContent")] - public JoinDataComplete RecievingContent = new JoinDataComplete( - new JoinData - { - JoinNumber = 204, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Recieving content from the far end", - JoinType = eJoinType.Digital, - JoinCapabilities = eJoinCapabilities.ToSIMPL - }); - - [JoinName("SelfviewPosition")] - public JoinDataComplete SelfviewPosition = new JoinDataComplete( - new JoinData - { - JoinNumber = 211, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Toggles selfview position", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("HoldAllCalls")] - public JoinDataComplete HoldAllCalls = new JoinDataComplete( - new JoinData - { - JoinNumber = 220, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Holds all calls", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("HoldCallsStart")] - public JoinDataComplete HoldCallsStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 221, - JoinSpan = 8 - }, - new JoinMetadata - { - Description = "Holds Call at specified index. FB reported on Call Status XSIG", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ResumeCallsStart")] - public JoinDataComplete ResumeCallsStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 231, - JoinSpan = 8 - }, - new JoinMetadata - { - Description = "Resume Call at specified index", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MultiSiteOptionIsEnabled")] - public JoinDataComplete MultiSiteOptionIsEnabled = new JoinDataComplete( - new JoinData - { - JoinNumber = 301, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Multi site option is enabled FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("AutoAnswerEnabled")] - public JoinDataComplete AutoAnswerEnabled = new JoinDataComplete( - new JoinData - { - JoinNumber = 302, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Auto Answer is enabled FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ParticipantAudioMuteToggleStart")] - public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 501, - JoinSpan = 50 - }, - new JoinMetadata - { - Description = "Toggles the participant's audio mute status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ParticipantVideoMuteToggleStart")] - public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 801, - JoinSpan = 50 - }, - new JoinMetadata - { - Description = "Toggles the participant's video mute status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ParticipantPinToggleStart")] - public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 1101, - JoinSpan = 50 - }, - new JoinMetadata - { - Description = "Toggles the participant's pin status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - - #endregion - - - +using System; +using PepperDash.Essentials.Core; +namespace PepperDash.Essentials.Core.Bridges.JoinMaps +{ + public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced + { + #region Digital + + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Device is Online", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SendDtmfToSpecificCallIndex")] + public JoinDataComplete SendDtmfToSpecificCallIndex = new JoinDataComplete( + new JoinData + { + JoinNumber = 10, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "If High, will send DTMF tones to the call set by SelectCall analog. If low sends DTMF tones to last connected call.", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Dtmf1")] + public JoinDataComplete Dtmf1 = new JoinDataComplete( + new JoinData + { + JoinNumber = 11, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 1", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Dtmf2")] + public JoinDataComplete Dtmf2 = new JoinDataComplete( + new JoinData + { + JoinNumber = 12, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 2", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Dtmf3")] + public JoinDataComplete Dtmf3 = new JoinDataComplete( + new JoinData + { + JoinNumber = 13, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 3", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Dtmf4")] + public JoinDataComplete Dtmf4 = new JoinDataComplete( + new JoinData + { + JoinNumber = 14, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 4", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Dtmf5")] + public JoinDataComplete Dtmf5 = new JoinDataComplete( + new JoinData + { + JoinNumber = 15, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 5", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Dtmf6")] + public JoinDataComplete Dtmf6 = new JoinDataComplete( + new JoinData + { + JoinNumber = 16, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 6", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Dtmf7")] + public JoinDataComplete Dtmf7 = new JoinDataComplete( + new JoinData + { + JoinNumber = 17, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 7", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Dtmf8")] + public JoinDataComplete Dtmf8 = new JoinDataComplete( + new JoinData + { + JoinNumber = 18, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 8", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Dtmf9")] + public JoinDataComplete Dtmf9 = new JoinDataComplete( + new JoinData + { + JoinNumber = 19, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 9", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Dtmf0")] + public JoinDataComplete Dtmf0 = new JoinDataComplete( + new JoinData + { + JoinNumber = 20, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 0", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DtmfStar")] + public JoinDataComplete DtmfStar = new JoinDataComplete( + new JoinData + { + JoinNumber = 21, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF *", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DtmfPound")] + public JoinDataComplete DtmfPound = new JoinDataComplete( + new JoinData + { + JoinNumber = 22, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF #", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("EndAllCalls")] + public JoinDataComplete EndAllCalls = new JoinDataComplete( + new JoinData + { + JoinNumber = 24, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "End All Calls", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("HookState")] + public JoinDataComplete HookState = new JoinDataComplete( + new JoinData + { + JoinNumber = 31, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Hook State", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SpeedDialStart")] + public JoinDataComplete SpeedDialStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 41, + JoinSpan = 4 + }, + new JoinMetadata + { + Description = "Speed Dial", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingCall")] + public JoinDataComplete IncomingCall = new JoinDataComplete( + new JoinData + { + JoinNumber = 50, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Incoming Call", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingAnswer")] + public JoinDataComplete IncomingAnswer = new JoinDataComplete( + new JoinData + { + JoinNumber = 51, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Answer Incoming Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingReject")] + public JoinDataComplete IncomingReject = new JoinDataComplete( + new JoinData + { + JoinNumber = 52, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reject Incoming Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ManualDial")] + public JoinDataComplete ManualDial = new JoinDataComplete( + new JoinData + { + JoinNumber = 71, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Dial manual string specified by CurrentDialString serial join", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialPhone")] + public JoinDataComplete DialPhone = new JoinDataComplete( + new JoinData + { + JoinNumber = 72, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Dial Phone", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("PhoneHookState")] + public JoinDataComplete PhoneHookState = new JoinDataComplete( + new JoinData + { + JoinNumber = 72, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Dial Phone", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("HangUpPhone")] + public JoinDataComplete HangUpPhone = new JoinDataComplete( + new JoinData + { + JoinNumber = 73, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Hang Up Phone", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("EndCallStart")] + public JoinDataComplete EndCallStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 81, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "End a specific call by call index. ", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("JoinAllCalls")] + public JoinDataComplete JoinAllCalls = new JoinDataComplete( + new JoinData + { + JoinNumber = 90, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join all calls", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("JoinCallStart")] + public JoinDataComplete JoinCallStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 91, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Join a specific call by call index. ", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectorySearchBusy")] + public JoinDataComplete DirectorySearchBusy = new JoinDataComplete( + new JoinData + { + JoinNumber = 100, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Search Busy FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryEntryIsContact")] + public JoinDataComplete DirectoryEntryIsContact = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Selected Entry Is Contact FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryLineSelected")] + public JoinDataComplete DirectoryLineSelected = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Line Selected FB", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryIsRoot")] + public JoinDataComplete DirectoryIsRoot = new JoinDataComplete( + new JoinData + { + JoinNumber = 102, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory is on Root FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryHasChanged")] + public JoinDataComplete DirectoryHasChanged = new JoinDataComplete( + new JoinData + { + JoinNumber = 103, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory has changed FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryRoot")] + public JoinDataComplete DirectoryRoot = new JoinDataComplete( + new JoinData + { + JoinNumber = 104, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Go to Directory Root", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryFolderBack")] + public JoinDataComplete DirectoryFolderBack = new JoinDataComplete( + new JoinData + { + JoinNumber = 105, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Go back one directory level", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryDialSelectedLine")] + public JoinDataComplete DirectoryDialSelectedLine = new JoinDataComplete( + new JoinData + { + JoinNumber = 106, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Dial selected directory line", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryDisableAutoDialSelectedLine")] + public JoinDataComplete DirectoryDisableAutoDialSelectedLine = new JoinDataComplete( + new JoinData + { + JoinNumber = 107, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Set high to disable automatic dialing of a contact when selected", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryDialSelectedContactMethod")] + public JoinDataComplete DirectoryDialSelectedContactMethod = new JoinDataComplete( + new JoinData + { + JoinNumber = 108, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to dial the selected contact method", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraTiltUp")] + public JoinDataComplete CameraTiltUp = new JoinDataComplete( + new JoinData + { + JoinNumber = 111, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Tilt Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraTiltDown")] + public JoinDataComplete CameraTiltDown = new JoinDataComplete( + new JoinData + { + JoinNumber = 112, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Tilt Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPanLeft")] + public JoinDataComplete CameraPanLeft = new JoinDataComplete( + new JoinData + { + JoinNumber = 113, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Pan Left", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPanRight")] + public JoinDataComplete CameraPanRight = new JoinDataComplete( + new JoinData + { + JoinNumber = 114, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Pan Right", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomIn")] + public JoinDataComplete CameraZoomIn = new JoinDataComplete( + new JoinData + { + JoinNumber = 115, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Zoom In", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomOut")] + public JoinDataComplete CameraZoomOut = new JoinDataComplete( + new JoinData + { + JoinNumber = 116, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Zoom Out", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraFocusNear")] + public JoinDataComplete CameraFocusNear = new JoinDataComplete( + new JoinData + { + JoinNumber = 117, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Focus Near", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraFocusFar")] + public JoinDataComplete CameraFocusFar = new JoinDataComplete( + new JoinData + { + JoinNumber = 118, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Focus Far", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraFocusAuto")] + public JoinDataComplete CameraFocusAuto = new JoinDataComplete( + new JoinData + { + JoinNumber = 119, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Auto Focus Trigger", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPresetSave")] + public JoinDataComplete CameraPresetSave = new JoinDataComplete( + new JoinData + { + JoinNumber = 121, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to save selected preset spcified by CameraPresetSelect analog join. FB will pulse for 3s when preset saved.", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeAuto")] + public JoinDataComplete CameraModeAuto = new JoinDataComplete( + new JoinData + { + JoinNumber = 131, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Mode Auto. Enables camera auto tracking mode, with feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeManual")] + public JoinDataComplete CameraModeManual = new JoinDataComplete( + new JoinData + { + JoinNumber = 132, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Mode Manual. Disables camera auto tracking mode, with feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeOff")] + public JoinDataComplete CameraModeOff = new JoinDataComplete( + new JoinData + { + JoinNumber = 133, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Mode Off. Disables camera video, with feedback. Works like video mute.", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSelfView")] + public JoinDataComplete CameraSelfView = new JoinDataComplete( + new JoinData + { + JoinNumber = 141, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Self View Toggle/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraLayout")] + public JoinDataComplete CameraLayout = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Layout Toggle", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsAutoMode")] + public JoinDataComplete CameraSupportsAutoMode = new JoinDataComplete( + new JoinData + { + JoinNumber = 143, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Supports Auto Mode FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsOffMode")] + public JoinDataComplete CameraSupportsOffMode = new JoinDataComplete( + new JoinData + { + JoinNumber = 144, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Supports Off Mode FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("UpdateMeetings")] + public JoinDataComplete UpdateMeetings = new JoinDataComplete( + new JoinData + { + JoinNumber = 160, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Update Meetings", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting1")] + public JoinDataComplete DialMeeting1 = new JoinDataComplete( + new JoinData + { + JoinNumber = 161, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join first meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting2")] + public JoinDataComplete DialMeeting2 = new JoinDataComplete( + new JoinData + { + JoinNumber = 162, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join second meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting3")] + public JoinDataComplete DialMeeting3 = new JoinDataComplete( + new JoinData + { + JoinNumber = 163, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join third meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteOn")] + public JoinDataComplete MicMuteOn = new JoinDataComplete( + new JoinData + { + JoinNumber = 171, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Mic Mute On", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteOff")] + public JoinDataComplete MicMuteOff = new JoinDataComplete( + new JoinData + { + JoinNumber = 172, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Mic Mute Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteToggle")] + public JoinDataComplete MicMuteToggle = new JoinDataComplete( + new JoinData + { + JoinNumber = 173, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Mic Mute Toggle", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeUp")] + public JoinDataComplete VolumeUp = new JoinDataComplete( + new JoinData + { + JoinNumber = 174, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeDown")] + public JoinDataComplete VolumeDown = new JoinDataComplete( + new JoinData + { + JoinNumber = 175, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteOn")] + public JoinDataComplete VolumeMuteOn = new JoinDataComplete( + new JoinData + { + JoinNumber = 176, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Mute On", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteOff")] + public JoinDataComplete VolumeMuteOff = new JoinDataComplete( + new JoinData + { + JoinNumber = 177, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Mute Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteToggle")] + public JoinDataComplete VolumeMuteToggle = new JoinDataComplete( + new JoinData + { + JoinNumber = 178, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Mute Toggle", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RemoveSelectedRecentCallItem")] + public JoinDataComplete RemoveSelectedRecentCallItem = new JoinDataComplete( + new JoinData + { + JoinNumber = 181, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to remove the selected recent call item specified by the SelectRecentCallItem analog join", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialSelectedRecentCallItem")] + public JoinDataComplete DialSelectedRecentCallItem = new JoinDataComplete( + new JoinData + { + JoinNumber = 182, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to dial the selected recent call item specified by the SelectRecentCallItem analog join", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceShareStart")] + public JoinDataComplete SourceShareStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 201, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Start Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceShareEnd")] + public JoinDataComplete SourceShareEnd = new JoinDataComplete( + new JoinData + { + JoinNumber = 202, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Stop Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("AutoShareWhileInCall")] + public JoinDataComplete SourceShareAutoStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 203, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "When high, will autostart sharing when a call is joined", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RecievingContent")] + public JoinDataComplete RecievingContent = new JoinDataComplete( + new JoinData + { + JoinNumber = 204, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Recieving content from the far end", + JoinType = eJoinType.Digital, + JoinCapabilities = eJoinCapabilities.ToSIMPL + }); + + [JoinName("SelfviewPosition")] + public JoinDataComplete SelfviewPosition = new JoinDataComplete( + new JoinData + { + JoinNumber = 211, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Toggles selfview position", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("HoldAllCalls")] + public JoinDataComplete HoldAllCalls = new JoinDataComplete( + new JoinData + { + JoinNumber = 220, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Holds all calls", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("HoldCallsStart")] + public JoinDataComplete HoldCallsStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 221, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Holds Call at specified index. FB reported on Call Status XSIG", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ResumeCallsStart")] + public JoinDataComplete ResumeCallsStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 231, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Resume Call at specified index", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MultiSiteOptionIsEnabled")] + public JoinDataComplete MultiSiteOptionIsEnabled = new JoinDataComplete( + new JoinData + { + JoinNumber = 301, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Multi site option is enabled FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("AutoAnswerEnabled")] + public JoinDataComplete AutoAnswerEnabled = new JoinDataComplete( + new JoinData + { + JoinNumber = 302, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Auto Answer is enabled FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ParticipantAudioMuteToggleStart")] + public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 501, + JoinSpan = 50 + }, + new JoinMetadata + { + Description = "Toggles the participant's audio mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ParticipantVideoMuteToggleStart")] + public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 801, + JoinSpan = 50 + }, + new JoinMetadata + { + Description = "Toggles the participant's video mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ParticipantPinToggleStart")] + public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 1101, + JoinSpan = 50 + }, + new JoinMetadata + { + Description = "Toggles the participant's pin status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + + #endregion + + + #region Analog // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set @@ -1160,1955 +1160,1955 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps Description = "Set/FB the number of meetings to display via the bridge xsig; default: 3 meetings.", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog - }); - - [JoinName("SelectCall")] - public JoinDataComplete SelectCall = new JoinDataComplete( - new JoinData - { - JoinNumber = 24, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Sets the selected Call for DTMF commands. Valid values 1-8", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - - [JoinName("ConnectedCallCount")] - public JoinDataComplete ConnectedCallCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 25, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Reports the number of currently connected calls", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("MinutesBeforeMeetingStart")] - public JoinDataComplete MinutesBeforeMeetingStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 41, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Minutes before meeting start that a meeting is joinable", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraNumberSelect")] - public JoinDataComplete CameraNumberSelect = new JoinDataComplete( - new JoinData - { - JoinNumber = 60, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Number Select/FB. 1 based index. Valid range is 1 to the value reported by CameraCount.", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraCount")] - public JoinDataComplete CameraCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 61, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Reports the number of cameras", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("DirectoryRowCount")] - public JoinDataComplete DirectoryRowCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 101, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Row Count FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("DirectorySelectRow")] - public JoinDataComplete DirectorySelectRow = new JoinDataComplete( - new JoinData - { - JoinNumber = 101, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Select Row", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("SelectedContactMethodCount")] - public JoinDataComplete SelectedContactMethodCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 102, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Reports the number of contact methods for the selected contact", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("SelectContactMethod")] - public JoinDataComplete SelectContactMethod = new JoinDataComplete( - new JoinData - { - JoinNumber = 103, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Selects a contact method by index", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraPresetSelect")] - public JoinDataComplete CameraPresetSelect = new JoinDataComplete( - new JoinData - { - JoinNumber = 121, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Preset Select", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("FarEndPresetSelect")] - public JoinDataComplete FarEndPresetSelect = new JoinDataComplete( - new JoinData - { - JoinNumber = 122, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Far End Preset Preset Select", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("ParticipantCount")] - public JoinDataComplete ParticipantCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 151, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Current Participant Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("Meeting Count Fb")] - public JoinDataComplete MeetingCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 161, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Meeting Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("VolumeLevel")] - public JoinDataComplete VolumeLevel = new JoinDataComplete( - new JoinData - { - JoinNumber = 174, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Volume Level", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("SelectRecentCallItem")] - public JoinDataComplete SelectRecentCallItem = new JoinDataComplete( - new JoinData - { - JoinNumber = 180, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Select/FB for Recent Call Item. Valid values 1 - 10", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("RecentCallOccurrenceType")] - public JoinDataComplete RecentCallOccurrenceType = new JoinDataComplete( - new JoinData - { - JoinNumber = 181, - JoinSpan = 10 - }, - new JoinMetadata - { - Description = "Recent Call Occurrence Type. [0-3] 0 = Unknown, 1 = Placed, 2 = Received, 3 = NoAnswer", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("RecentCallCount")] - public JoinDataComplete RecentCallCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 191, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Recent Call Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - #endregion - - - - #region Serials - - [JoinName("CurrentDialString")] - public JoinDataComplete CurrentDialString = new JoinDataComplete( - new JoinData - { - JoinNumber = 1, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Value to dial when ManualDial digital join is pulsed", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("PhoneDialString")] - public JoinDataComplete PhoneDialString = new JoinDataComplete( - new JoinData - { - JoinNumber = 2, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Phone Dial String", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentCallData")] - public JoinDataComplete CurrentCallData = new JoinDataComplete( - new JoinData - { - JoinNumber = 2, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Current Call Data - XSIG", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CallDirection")] - public JoinDataComplete CallDirection = new JoinDataComplete( - new JoinData - { - JoinNumber = 22, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Current Call Direction", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallName")] - public JoinDataComplete IncomingCallName = new JoinDataComplete( - new JoinData - { - JoinNumber = 51, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Incoming Call Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallNumber")] - public JoinDataComplete IncomingCallNumber = new JoinDataComplete( - new JoinData - { - JoinNumber = 52, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Incoming Call Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - - [JoinName("DirectorySearchString")] - public JoinDataComplete DirectorySearchString = new JoinDataComplete( - new JoinData - { - JoinNumber = 100, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Search String", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntries")] - public JoinDataComplete DirectoryEntries = new JoinDataComplete( - new JoinData - { - JoinNumber = 101, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Entries - XSig, 255 entries", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("Schedule")] - public JoinDataComplete Schedule = new JoinDataComplete( - new JoinData - { - JoinNumber = 102, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Schedule Data - XSIG", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("ContactMethods")] - public JoinDataComplete ContactMethods = new JoinDataComplete( - new JoinData - { - JoinNumber = 103, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Contact Methods - XSig, 10 entries", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CameraPresetNames")] - public JoinDataComplete CameraPresetNames = new JoinDataComplete( - new JoinData - { - JoinNumber = 121, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Preset Names - XSIG, max of 15", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentLayoutStringFb")] - public JoinDataComplete CurrentLayoutStringFb = new JoinDataComplete( - new JoinData - { - JoinNumber = 141, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Current Layout Fb", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentParticipants")] - public JoinDataComplete CurrentParticipants = new JoinDataComplete( - new JoinData - { - JoinNumber = 151, - JoinSpan = 1 - }, - new JoinMetadata() - { - Description = "Current Participants XSig", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CameraNamesFb")] - public JoinDataComplete CameraNamesFb = new JoinDataComplete( - new JoinData - { - JoinNumber = 161, - JoinSpan = 10 - }, - new JoinMetadata - { - Description = "Camera Name Fb", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SelectedRecentCallName")] - public JoinDataComplete SelectedRecentCallName = new JoinDataComplete( - new JoinData - { - JoinNumber = 171, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Selected Recent Call Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SelectedRecentCallNumber")] - public JoinDataComplete SelectedRecentCallNumber = new JoinDataComplete( - new JoinData - { - JoinNumber = 172, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Selected Recent Call Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("RecentCallNamesStart")] - public JoinDataComplete RecentCallNamesStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 181, - JoinSpan = 10 - }, - new JoinMetadata - { - Description = "Recent Call Names", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("RecentCallTimesStart")] - public JoinDataComplete RecentCallTimesStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 191, - JoinSpan = 10 - }, - new JoinMetadata - { - Description = "Recent Calls Times", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentSource")] - public JoinDataComplete CurrentSource = new JoinDataComplete( - new JoinData - { - JoinNumber = 201, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Current Source", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SelfviewPositionFb")] - public JoinDataComplete SelfviewPositionFb = new JoinDataComplete( - new JoinData - { - JoinNumber = 211, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "advance selfview position", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DeviceIpAddresss")] - public JoinDataComplete DeviceIpAddresss = new JoinDataComplete( - new JoinData - { - JoinNumber = 301, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "IP Address of device", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SipPhoneNumber")] - public JoinDataComplete SipPhoneNumber = new JoinDataComplete( - new JoinData - { - JoinNumber = 302, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "SIP phone number of device", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("E164Alias")] - public JoinDataComplete E164Alias = new JoinDataComplete( - new JoinData - { - JoinNumber = 303, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "E164 alias of device", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("H323Id")] - public JoinDataComplete H323Id = new JoinDataComplete( - new JoinData - { - JoinNumber = 304, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "H323 ID of device", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SipUri")] - public JoinDataComplete SipUri = new JoinDataComplete( - new JoinData - { - JoinNumber = 305, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "SIP URI of device", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntrySelectedName")] - public JoinDataComplete DirectoryEntrySelectedName = new JoinDataComplete( - new JoinData - { - JoinNumber = 356, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Selected Directory Entry Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntrySelectedNumber")] - public JoinDataComplete DirectoryEntrySelectedNumber = new JoinDataComplete( - new JoinData - { - JoinNumber = 357, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Selected Directory Entry Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectorySelectedFolderName")] - public JoinDataComplete DirectorySelectedFolderName = new JoinDataComplete( - new JoinData - { - JoinNumber = 358, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Selected Directory Folder Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - #endregion - - - public VideoCodecControllerJoinMap(uint joinStart) - : base(joinStart, typeof(VideoCodecControllerJoinMap)) - { - } - - public VideoCodecControllerJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } - } -} - - -namespace PepperDash_Essentials_Core.Bridges.JoinMaps -{ - [Obsolete("Use PepperDash.Essentials.Core.Bridges.JoinMaps")] - public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced - { - - #region Digital - - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete( - new JoinData - { - JoinNumber = 1, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Device is Online", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("1")] - public JoinDataComplete Dtmf1 = new JoinDataComplete( - new JoinData - { - JoinNumber = 11, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 1", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("2")] - public JoinDataComplete Dtmf2 = new JoinDataComplete( - new JoinData - { - JoinNumber = 12, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 2", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("3")] - public JoinDataComplete Dtmf3 = new JoinDataComplete( - new JoinData - { - JoinNumber = 13, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 3", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("4")] - public JoinDataComplete Dtmf4 = new JoinDataComplete( - new JoinData - { - JoinNumber = 14, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 4", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("5")] - public JoinDataComplete Dtmf5 = new JoinDataComplete( - new JoinData - { - JoinNumber = 15, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 5", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("6")] - public JoinDataComplete Dtmf6 = new JoinDataComplete( - new JoinData - { - JoinNumber = 16, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 6", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("7")] - public JoinDataComplete Dtmf7 = new JoinDataComplete( - new JoinData - { - JoinNumber = 17, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 7", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("8")] - public JoinDataComplete Dtmf8 = new JoinDataComplete( - new JoinData - { - JoinNumber = 18, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 8", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("9")] - public JoinDataComplete Dtmf9 = new JoinDataComplete( - new JoinData - { - JoinNumber = 19, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 9", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("0")] - public JoinDataComplete Dtmf0 = new JoinDataComplete( - new JoinData - { - JoinNumber = 20, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF 0", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("*")] - public JoinDataComplete DtmfStar = new JoinDataComplete( - new JoinData - { - JoinNumber = 21, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF *", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("#")] - public JoinDataComplete DtmfPound = new JoinDataComplete( - new JoinData - { - JoinNumber = 22, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "DTMF #", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("EndCall")] - public JoinDataComplete EndCall = new JoinDataComplete( - new JoinData - { - JoinNumber = 24, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Hang Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("HookState")] - public JoinDataComplete HookState = new JoinDataComplete( - new JoinData - { - JoinNumber = 31, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Current Hook State", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SpeedDialStart")] - public JoinDataComplete SpeedDialStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 41, - JoinSpan = 4 - }, - new JoinMetadata - { - Description = "Speed Dial", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingCall")] - public JoinDataComplete IncomingCall = new JoinDataComplete( - new JoinData - { - JoinNumber = 50, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Incoming Call", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingAnswer")] - public JoinDataComplete IncomingAnswer = new JoinDataComplete( - new JoinData - { - JoinNumber = 51, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Answer Incoming Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingReject")] - public JoinDataComplete IncomingReject = new JoinDataComplete( - new JoinData - { - JoinNumber = 52, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Reject Incoming Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ManualDial")] - public JoinDataComplete ManualDial = new JoinDataComplete( - new JoinData - { - JoinNumber = 71, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Dial manual string", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialPhoneCall")] - public JoinDataComplete DialPhone = new JoinDataComplete( - new JoinData - { - JoinNumber = 72, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Dial Phone", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("PhoneHookState")] - public JoinDataComplete PhoneHookState = new JoinDataComplete( - new JoinData - { - JoinNumber = 72, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Dial Phone", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("EndPhoneCall")] - public JoinDataComplete HangUpPhone = new JoinDataComplete( - new JoinData - { - JoinNumber = 73, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Hang Up PHone", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectorySearchBusy")] - public JoinDataComplete DirectorySearchBusy = new JoinDataComplete( - new JoinData - { - JoinNumber = 100, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Search Busy FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryEntryIsContact")] - public JoinDataComplete DirectoryEntryIsContact = new JoinDataComplete( - new JoinData - { - JoinNumber = 101, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Selected Entry Is Contact FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryLineSelected")] - public JoinDataComplete DirectoryLineSelected = new JoinDataComplete( - new JoinData - { - JoinNumber = 101, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Line Selected FB", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryIsRoot")] - public JoinDataComplete DirectoryIsRoot = new JoinDataComplete( - new JoinData - { - JoinNumber = 102, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory is on Root FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryHasChanged")] - public JoinDataComplete DirectoryHasChanged = new JoinDataComplete( - new JoinData - { - JoinNumber = 103, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory has changed FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryRoot")] - public JoinDataComplete DirectoryRoot = new JoinDataComplete( - new JoinData - { - JoinNumber = 104, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Go to Directory Root", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryFolderBack")] - public JoinDataComplete DirectoryFolderBack = new JoinDataComplete( - new JoinData - { - JoinNumber = 105, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Go back one directory level", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryDialSelectedLine")] - public JoinDataComplete DirectoryDialSelectedLine = new JoinDataComplete( - new JoinData - { - JoinNumber = 106, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Dial selected directory line", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - - [JoinName("CameraTiltUp")] - public JoinDataComplete CameraTiltUp = new JoinDataComplete( - new JoinData - { - JoinNumber = 111, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Tilt Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraTiltDown")] - public JoinDataComplete CameraTiltDown = new JoinDataComplete( - new JoinData - { - JoinNumber = 112, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Tilt Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPanLeft")] - public JoinDataComplete CameraPanLeft = new JoinDataComplete( - new JoinData - { - JoinNumber = 113, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Pan Left", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPanRight")] - public JoinDataComplete CameraPanRight = new JoinDataComplete( - new JoinData - { - JoinNumber = 114, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Pan Right", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraZoomIn")] - public JoinDataComplete CameraZoomIn = new JoinDataComplete( - new JoinData - { - JoinNumber = 115, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Zoom In", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraZoomOut")] - public JoinDataComplete CameraZoomOut = new JoinDataComplete( - new JoinData - { - JoinNumber = 116, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Zoom Out", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPresetSave")] - public JoinDataComplete CameraPresetSave = new JoinDataComplete( - new JoinData - { - JoinNumber = 121, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Save Selected Preset", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeAuto")] - public JoinDataComplete CameraModeAuto = new JoinDataComplete( - new JoinData - { - JoinNumber = 131, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Mode Auto", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeManual")] - public JoinDataComplete CameraModeManual = new JoinDataComplete( - new JoinData - { - JoinNumber = 132, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Mode Manual", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeOff")] - public JoinDataComplete CameraModeOff = new JoinDataComplete( - new JoinData - { - JoinNumber = 133, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Mode Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSelfView")] - public JoinDataComplete CameraSelfView = new JoinDataComplete( - new JoinData - { - JoinNumber = 141, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Self View Toggle/FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraLayout")] - public JoinDataComplete CameraLayout = new JoinDataComplete( - new JoinData - { - JoinNumber = 142, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Layout Toggle", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSupportsAutoMode")] - public JoinDataComplete CameraSupportsAutoMode = new JoinDataComplete( - new JoinData - { - JoinNumber = 143, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Supports Auto Mode FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSupportsOffMode")] - public JoinDataComplete CameraSupportsOffMode = new JoinDataComplete( - new JoinData - { - JoinNumber = 144, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Supports Off Mode FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("UpdateMeetings")] - public JoinDataComplete UpdateMeetings = new JoinDataComplete( - new JoinData - { - JoinNumber = 160, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Update Meetings", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting1")] - public JoinDataComplete DialMeeting1 = new JoinDataComplete( - new JoinData - { - JoinNumber = 161, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Join first meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting2")] - public JoinDataComplete DialMeeting2 = new JoinDataComplete( - new JoinData - { - JoinNumber = 162, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Join second meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting3")] - public JoinDataComplete DialMeeting3 = new JoinDataComplete( - new JoinData - { - JoinNumber = 163, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Join third meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MicMuteOn")] - public JoinDataComplete MicMuteOn = new JoinDataComplete( - new JoinData - { - JoinNumber = 171, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Mic Mute On", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MicMuteOff")] - public JoinDataComplete MicMuteOff = new JoinDataComplete( - new JoinData - { - JoinNumber = 172, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Mic Mute Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MicMuteToggle")] - public JoinDataComplete MicMuteToggle = new JoinDataComplete( - new JoinData - { - JoinNumber = 173, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Mic Mute Toggle", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeUp")] - public JoinDataComplete VolumeUp = new JoinDataComplete( - new JoinData - { - JoinNumber = 174, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Volume Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeDown")] - public JoinDataComplete VolumeDown = new JoinDataComplete( - new JoinData - { - JoinNumber = 175, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Volume Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeMuteOn")] - public JoinDataComplete VolumeMuteOn = new JoinDataComplete( - new JoinData - { - JoinNumber = 176, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Volume Mute On", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeMuteOff")] - public JoinDataComplete VolumeMuteOff = new JoinDataComplete( - new JoinData - { - JoinNumber = 177, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Volume Mute Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeMuteToggle")] - public JoinDataComplete VolumeMuteToggle = new JoinDataComplete( - new JoinData - { - JoinNumber = 178, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Volume Mute Toggle", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceShareStart")] - public JoinDataComplete SourceShareStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 201, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Start Sharing & Feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceShareEnd")] - public JoinDataComplete SourceShareEnd = new JoinDataComplete( - new JoinData - { - JoinNumber = 202, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Stop Sharing & Feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("AutoShareWhileInCall")] - public JoinDataComplete SourceShareAutoStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 203, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "When high, will autostart sharing when a call is joined", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("RecievingContent")] - public JoinDataComplete RecievingContent = new JoinDataComplete( - new JoinData - { - JoinNumber = 204, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Recieving content from the far end", - JoinType = eJoinType.Digital, - JoinCapabilities = eJoinCapabilities.ToSIMPL - }); - - [JoinName("SelfviewPosition")] - public JoinDataComplete SelfviewPosition = new JoinDataComplete( - new JoinData - { - JoinNumber = 211, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "advance selfview position", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ParticipantAudioMuteToggleStart")] - public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 500, - JoinSpan = 50 - }, - new JoinMetadata - { - Description = "Toggles the participant's audio mute status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ParticipantVideoMuteToggleStart")] - public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 800, - JoinSpan = 50 - }, - new JoinMetadata - { - Description = "Toggles the participant's video mute status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ParticipantPinToggleStart")] - public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 1100, - JoinSpan = 50 - }, - new JoinMetadata - { - Description = "Toggles the participant's pin status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - #endregion - - - - #region Analog - - [JoinName("MinutesBeforeMeetingStart")] - public JoinDataComplete MinutesBeforeMeetingStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 41, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Minutes before meeting start that a meeting is joinable", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraNumberSelect")] - public JoinDataComplete CameraNumberSelect = new JoinDataComplete( - new JoinData - { - JoinNumber = 60, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Number Select/FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("DirectoryRowCount")] - public JoinDataComplete DirectoryRowCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 101, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Row Count FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("DirectorySelectRow")] - public JoinDataComplete DirectorySelectRow = new JoinDataComplete( - new JoinData - { - JoinNumber = 101, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Select Row", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraPresetSelect")] - public JoinDataComplete CameraPresetSelect = new JoinDataComplete( - new JoinData - { - JoinNumber = 121, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Preset Select", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("ParticipantCount")] - public JoinDataComplete ParticipantCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 151, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Current Participant Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("Meeting Count Fb")] - public JoinDataComplete MeetingCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 161, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Meeting Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("VolumeLevel")] - public JoinDataComplete VolumeLevel = new JoinDataComplete( - new JoinData - { - JoinNumber = 174, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Volume Level", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - #endregion - - - - #region Serials - - [JoinName("CurrentDialString")] - public JoinDataComplete CurrentDialString = new JoinDataComplete( - new JoinData - { - JoinNumber = 1, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Current Dial String", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("PhoneString")] - public JoinDataComplete PhoneDialString = new JoinDataComplete( - new JoinData - { - JoinNumber = 2, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Phone Dial String", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentCallName")] - public JoinDataComplete CurrentCallData = new JoinDataComplete( - new JoinData - { - JoinNumber = 2, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Current Call Data - XSIG", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CallDirection")] - public JoinDataComplete CallDirection = new JoinDataComplete( - new JoinData - { - JoinNumber = 22, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Current Call Direction", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallName")] - public JoinDataComplete IncomingCallName = new JoinDataComplete( - new JoinData - { - JoinNumber = 51, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Incoming Call Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallNumber")] - public JoinDataComplete IncomingCallNumber = new JoinDataComplete( - new JoinData - { - JoinNumber = 52, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Incoming Call Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - - [JoinName("DirectorySearchString")] - public JoinDataComplete DirectorySearchString = new JoinDataComplete( - new JoinData - { - JoinNumber = 100, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Search String", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntries")] - public JoinDataComplete DirectoryEntries = new JoinDataComplete( - new JoinData - { - JoinNumber = 101, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Entries - XSig, 255 entries", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("Schedule")] - public JoinDataComplete Schedule = new JoinDataComplete( - new JoinData - { - JoinNumber = 102, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Schedule Data - XSIG", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CameraPresetNames")] - public JoinDataComplete CameraPresetNames = new JoinDataComplete( - new JoinData - { - JoinNumber = 121, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Preset Names - XSIG, max of 15", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CameraLayoutStringFb")] - public JoinDataComplete CameraLayoutStringFb = new JoinDataComplete( - new JoinData - { - JoinNumber = 141, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Current Layout Fb", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentParticipants")] - public JoinDataComplete CurrentParticipants = new JoinDataComplete( - new JoinData - { - JoinNumber = 151, - JoinSpan = 1 - }, - new JoinMetadata() - { - Description = "Current Participants XSig", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentSource")] - public JoinDataComplete CurrentSource = new JoinDataComplete( - new JoinData - { - JoinNumber = 201, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Current Source", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SelfviewPositionFb")] - public JoinDataComplete SelfviewPositionFb = new JoinDataComplete( - new JoinData - { - JoinNumber = 211, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "advance selfview position", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntrySelectedName")] - public JoinDataComplete DirectoryEntrySelectedName = new JoinDataComplete( - new JoinData - { - JoinNumber = 356, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Selected Directory Entry Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntrySelectedNumber")] - public JoinDataComplete DirectoryEntrySelectedNumber = new JoinDataComplete( - new JoinData - { - JoinNumber = 357, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Selected Directory Entry Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectorySelectedFolderName")] - public JoinDataComplete DirectorySelectedFolderName = new JoinDataComplete( - new JoinData - { - JoinNumber = 358, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Selected Directory Folder Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - #endregion - - - public VideoCodecControllerJoinMap(uint joinStart) - : base(joinStart, typeof(VideoCodecControllerJoinMap)) - { - } - - public VideoCodecControllerJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } - } -} + }); + + [JoinName("SelectCall")] + public JoinDataComplete SelectCall = new JoinDataComplete( + new JoinData + { + JoinNumber = 24, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Sets the selected Call for DTMF commands. Valid values 1-8", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + + [JoinName("ConnectedCallCount")] + public JoinDataComplete ConnectedCallCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 25, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the number of currently connected calls", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("MinutesBeforeMeetingStart")] + public JoinDataComplete MinutesBeforeMeetingStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 41, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Minutes before meeting start that a meeting is joinable", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraNumberSelect")] + public JoinDataComplete CameraNumberSelect = new JoinDataComplete( + new JoinData + { + JoinNumber = 60, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Number Select/FB. 1 based index. Valid range is 1 to the value reported by CameraCount.", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraCount")] + public JoinDataComplete CameraCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 61, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the number of cameras", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectoryRowCount")] + public JoinDataComplete DirectoryRowCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Row Count FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectorySelectRow")] + public JoinDataComplete DirectorySelectRow = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Select Row", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("SelectedContactMethodCount")] + public JoinDataComplete SelectedContactMethodCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 102, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the number of contact methods for the selected contact", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("SelectContactMethod")] + public JoinDataComplete SelectContactMethod = new JoinDataComplete( + new JoinData + { + JoinNumber = 103, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selects a contact method by index", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraPresetSelect")] + public JoinDataComplete CameraPresetSelect = new JoinDataComplete( + new JoinData + { + JoinNumber = 121, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Preset Select", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("FarEndPresetSelect")] + public JoinDataComplete FarEndPresetSelect = new JoinDataComplete( + new JoinData + { + JoinNumber = 122, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Far End Preset Preset Select", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("ParticipantCount")] + public JoinDataComplete ParticipantCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 151, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Participant Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("Meeting Count Fb")] + public JoinDataComplete MeetingCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 161, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Meeting Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("VolumeLevel")] + public JoinDataComplete VolumeLevel = new JoinDataComplete( + new JoinData + { + JoinNumber = 174, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Level", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("SelectRecentCallItem")] + public JoinDataComplete SelectRecentCallItem = new JoinDataComplete( + new JoinData + { + JoinNumber = 180, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Select/FB for Recent Call Item. Valid values 1 - 10", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("RecentCallOccurrenceType")] + public JoinDataComplete RecentCallOccurrenceType = new JoinDataComplete( + new JoinData + { + JoinNumber = 181, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Recent Call Occurrence Type. [0-3] 0 = Unknown, 1 = Placed, 2 = Received, 3 = NoAnswer", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("RecentCallCount")] + public JoinDataComplete RecentCallCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 191, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Recent Call Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + #endregion + + + + #region Serials + + [JoinName("CurrentDialString")] + public JoinDataComplete CurrentDialString = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Value to dial when ManualDial digital join is pulsed", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("PhoneDialString")] + public JoinDataComplete PhoneDialString = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Phone Dial String", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentCallData")] + public JoinDataComplete CurrentCallData = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Call Data - XSIG", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CallDirection")] + public JoinDataComplete CallDirection = new JoinDataComplete( + new JoinData + { + JoinNumber = 22, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Call Direction", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallName")] + public JoinDataComplete IncomingCallName = new JoinDataComplete( + new JoinData + { + JoinNumber = 51, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Incoming Call Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallNumber")] + public JoinDataComplete IncomingCallNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 52, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Incoming Call Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + + [JoinName("DirectorySearchString")] + public JoinDataComplete DirectorySearchString = new JoinDataComplete( + new JoinData + { + JoinNumber = 100, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Search String", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntries")] + public JoinDataComplete DirectoryEntries = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Entries - XSig, 255 entries", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("Schedule")] + public JoinDataComplete Schedule = new JoinDataComplete( + new JoinData + { + JoinNumber = 102, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Schedule Data - XSIG", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("ContactMethods")] + public JoinDataComplete ContactMethods = new JoinDataComplete( + new JoinData + { + JoinNumber = 103, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Contact Methods - XSig, 10 entries", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraPresetNames")] + public JoinDataComplete CameraPresetNames = new JoinDataComplete( + new JoinData + { + JoinNumber = 121, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Preset Names - XSIG, max of 15", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentLayoutStringFb")] + public JoinDataComplete CurrentLayoutStringFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 141, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Layout Fb", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentParticipants")] + public JoinDataComplete CurrentParticipants = new JoinDataComplete( + new JoinData + { + JoinNumber = 151, + JoinSpan = 1 + }, + new JoinMetadata() + { + Description = "Current Participants XSig", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraNamesFb")] + public JoinDataComplete CameraNamesFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 161, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Camera Name Fb", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelectedRecentCallName")] + public JoinDataComplete SelectedRecentCallName = new JoinDataComplete( + new JoinData + { + JoinNumber = 171, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Recent Call Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelectedRecentCallNumber")] + public JoinDataComplete SelectedRecentCallNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 172, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Recent Call Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("RecentCallNamesStart")] + public JoinDataComplete RecentCallNamesStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 181, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Recent Call Names", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("RecentCallTimesStart")] + public JoinDataComplete RecentCallTimesStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 191, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Recent Calls Times", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentSource")] + public JoinDataComplete CurrentSource = new JoinDataComplete( + new JoinData + { + JoinNumber = 201, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Source", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelfviewPositionFb")] + public JoinDataComplete SelfviewPositionFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 211, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "advance selfview position", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DeviceIpAddresss")] + public JoinDataComplete DeviceIpAddresss = new JoinDataComplete( + new JoinData + { + JoinNumber = 301, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "IP Address of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SipPhoneNumber")] + public JoinDataComplete SipPhoneNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 302, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "SIP phone number of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("E164Alias")] + public JoinDataComplete E164Alias = new JoinDataComplete( + new JoinData + { + JoinNumber = 303, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "E164 alias of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("H323Id")] + public JoinDataComplete H323Id = new JoinDataComplete( + new JoinData + { + JoinNumber = 304, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "H323 ID of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SipUri")] + public JoinDataComplete SipUri = new JoinDataComplete( + new JoinData + { + JoinNumber = 305, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "SIP URI of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntrySelectedName")] + public JoinDataComplete DirectoryEntrySelectedName = new JoinDataComplete( + new JoinData + { + JoinNumber = 356, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Directory Entry Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntrySelectedNumber")] + public JoinDataComplete DirectoryEntrySelectedNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 357, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Directory Entry Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectorySelectedFolderName")] + public JoinDataComplete DirectorySelectedFolderName = new JoinDataComplete( + new JoinData + { + JoinNumber = 358, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Directory Folder Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + #endregion + + + public VideoCodecControllerJoinMap(uint joinStart) + : base(joinStart, typeof(VideoCodecControllerJoinMap)) + { + } + + public VideoCodecControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { + } + } +} + + +namespace PepperDash_Essentials_Core.Bridges.JoinMaps +{ + [Obsolete("Use PepperDash.Essentials.Core.Bridges.JoinMaps")] + public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced + { + + #region Digital + + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Device is Online", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("1")] + public JoinDataComplete Dtmf1 = new JoinDataComplete( + new JoinData + { + JoinNumber = 11, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 1", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("2")] + public JoinDataComplete Dtmf2 = new JoinDataComplete( + new JoinData + { + JoinNumber = 12, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 2", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("3")] + public JoinDataComplete Dtmf3 = new JoinDataComplete( + new JoinData + { + JoinNumber = 13, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 3", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("4")] + public JoinDataComplete Dtmf4 = new JoinDataComplete( + new JoinData + { + JoinNumber = 14, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 4", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("5")] + public JoinDataComplete Dtmf5 = new JoinDataComplete( + new JoinData + { + JoinNumber = 15, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 5", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("6")] + public JoinDataComplete Dtmf6 = new JoinDataComplete( + new JoinData + { + JoinNumber = 16, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 6", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("7")] + public JoinDataComplete Dtmf7 = new JoinDataComplete( + new JoinData + { + JoinNumber = 17, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 7", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("8")] + public JoinDataComplete Dtmf8 = new JoinDataComplete( + new JoinData + { + JoinNumber = 18, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 8", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("9")] + public JoinDataComplete Dtmf9 = new JoinDataComplete( + new JoinData + { + JoinNumber = 19, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 9", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("0")] + public JoinDataComplete Dtmf0 = new JoinDataComplete( + new JoinData + { + JoinNumber = 20, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 0", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("*")] + public JoinDataComplete DtmfStar = new JoinDataComplete( + new JoinData + { + JoinNumber = 21, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF *", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("#")] + public JoinDataComplete DtmfPound = new JoinDataComplete( + new JoinData + { + JoinNumber = 22, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF #", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("EndCall")] + public JoinDataComplete EndCall = new JoinDataComplete( + new JoinData + { + JoinNumber = 24, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Hang Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("HookState")] + public JoinDataComplete HookState = new JoinDataComplete( + new JoinData + { + JoinNumber = 31, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Hook State", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SpeedDialStart")] + public JoinDataComplete SpeedDialStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 41, + JoinSpan = 4 + }, + new JoinMetadata + { + Description = "Speed Dial", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingCall")] + public JoinDataComplete IncomingCall = new JoinDataComplete( + new JoinData + { + JoinNumber = 50, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Incoming Call", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingAnswer")] + public JoinDataComplete IncomingAnswer = new JoinDataComplete( + new JoinData + { + JoinNumber = 51, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Answer Incoming Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingReject")] + public JoinDataComplete IncomingReject = new JoinDataComplete( + new JoinData + { + JoinNumber = 52, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reject Incoming Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ManualDial")] + public JoinDataComplete ManualDial = new JoinDataComplete( + new JoinData + { + JoinNumber = 71, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Dial manual string", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialPhoneCall")] + public JoinDataComplete DialPhone = new JoinDataComplete( + new JoinData + { + JoinNumber = 72, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Dial Phone", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("PhoneHookState")] + public JoinDataComplete PhoneHookState = new JoinDataComplete( + new JoinData + { + JoinNumber = 72, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Dial Phone", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("EndPhoneCall")] + public JoinDataComplete HangUpPhone = new JoinDataComplete( + new JoinData + { + JoinNumber = 73, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Hang Up PHone", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectorySearchBusy")] + public JoinDataComplete DirectorySearchBusy = new JoinDataComplete( + new JoinData + { + JoinNumber = 100, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Search Busy FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryEntryIsContact")] + public JoinDataComplete DirectoryEntryIsContact = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Selected Entry Is Contact FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryLineSelected")] + public JoinDataComplete DirectoryLineSelected = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Line Selected FB", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryIsRoot")] + public JoinDataComplete DirectoryIsRoot = new JoinDataComplete( + new JoinData + { + JoinNumber = 102, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory is on Root FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryHasChanged")] + public JoinDataComplete DirectoryHasChanged = new JoinDataComplete( + new JoinData + { + JoinNumber = 103, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory has changed FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryRoot")] + public JoinDataComplete DirectoryRoot = new JoinDataComplete( + new JoinData + { + JoinNumber = 104, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Go to Directory Root", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryFolderBack")] + public JoinDataComplete DirectoryFolderBack = new JoinDataComplete( + new JoinData + { + JoinNumber = 105, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Go back one directory level", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryDialSelectedLine")] + public JoinDataComplete DirectoryDialSelectedLine = new JoinDataComplete( + new JoinData + { + JoinNumber = 106, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Dial selected directory line", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("CameraTiltUp")] + public JoinDataComplete CameraTiltUp = new JoinDataComplete( + new JoinData + { + JoinNumber = 111, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Tilt Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraTiltDown")] + public JoinDataComplete CameraTiltDown = new JoinDataComplete( + new JoinData + { + JoinNumber = 112, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Tilt Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPanLeft")] + public JoinDataComplete CameraPanLeft = new JoinDataComplete( + new JoinData + { + JoinNumber = 113, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Pan Left", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPanRight")] + public JoinDataComplete CameraPanRight = new JoinDataComplete( + new JoinData + { + JoinNumber = 114, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Pan Right", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomIn")] + public JoinDataComplete CameraZoomIn = new JoinDataComplete( + new JoinData + { + JoinNumber = 115, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Zoom In", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomOut")] + public JoinDataComplete CameraZoomOut = new JoinDataComplete( + new JoinData + { + JoinNumber = 116, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Zoom Out", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPresetSave")] + public JoinDataComplete CameraPresetSave = new JoinDataComplete( + new JoinData + { + JoinNumber = 121, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Save Selected Preset", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeAuto")] + public JoinDataComplete CameraModeAuto = new JoinDataComplete( + new JoinData + { + JoinNumber = 131, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Mode Auto", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeManual")] + public JoinDataComplete CameraModeManual = new JoinDataComplete( + new JoinData + { + JoinNumber = 132, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Mode Manual", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeOff")] + public JoinDataComplete CameraModeOff = new JoinDataComplete( + new JoinData + { + JoinNumber = 133, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Mode Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSelfView")] + public JoinDataComplete CameraSelfView = new JoinDataComplete( + new JoinData + { + JoinNumber = 141, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Self View Toggle/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraLayout")] + public JoinDataComplete CameraLayout = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Layout Toggle", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsAutoMode")] + public JoinDataComplete CameraSupportsAutoMode = new JoinDataComplete( + new JoinData + { + JoinNumber = 143, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Supports Auto Mode FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsOffMode")] + public JoinDataComplete CameraSupportsOffMode = new JoinDataComplete( + new JoinData + { + JoinNumber = 144, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Supports Off Mode FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("UpdateMeetings")] + public JoinDataComplete UpdateMeetings = new JoinDataComplete( + new JoinData + { + JoinNumber = 160, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Update Meetings", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting1")] + public JoinDataComplete DialMeeting1 = new JoinDataComplete( + new JoinData + { + JoinNumber = 161, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join first meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting2")] + public JoinDataComplete DialMeeting2 = new JoinDataComplete( + new JoinData + { + JoinNumber = 162, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join second meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting3")] + public JoinDataComplete DialMeeting3 = new JoinDataComplete( + new JoinData + { + JoinNumber = 163, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join third meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteOn")] + public JoinDataComplete MicMuteOn = new JoinDataComplete( + new JoinData + { + JoinNumber = 171, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Mic Mute On", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteOff")] + public JoinDataComplete MicMuteOff = new JoinDataComplete( + new JoinData + { + JoinNumber = 172, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Mic Mute Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteToggle")] + public JoinDataComplete MicMuteToggle = new JoinDataComplete( + new JoinData + { + JoinNumber = 173, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Mic Mute Toggle", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeUp")] + public JoinDataComplete VolumeUp = new JoinDataComplete( + new JoinData + { + JoinNumber = 174, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeDown")] + public JoinDataComplete VolumeDown = new JoinDataComplete( + new JoinData + { + JoinNumber = 175, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteOn")] + public JoinDataComplete VolumeMuteOn = new JoinDataComplete( + new JoinData + { + JoinNumber = 176, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Mute On", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteOff")] + public JoinDataComplete VolumeMuteOff = new JoinDataComplete( + new JoinData + { + JoinNumber = 177, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Mute Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteToggle")] + public JoinDataComplete VolumeMuteToggle = new JoinDataComplete( + new JoinData + { + JoinNumber = 178, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Mute Toggle", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceShareStart")] + public JoinDataComplete SourceShareStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 201, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Start Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceShareEnd")] + public JoinDataComplete SourceShareEnd = new JoinDataComplete( + new JoinData + { + JoinNumber = 202, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Stop Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("AutoShareWhileInCall")] + public JoinDataComplete SourceShareAutoStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 203, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "When high, will autostart sharing when a call is joined", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RecievingContent")] + public JoinDataComplete RecievingContent = new JoinDataComplete( + new JoinData + { + JoinNumber = 204, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Recieving content from the far end", + JoinType = eJoinType.Digital, + JoinCapabilities = eJoinCapabilities.ToSIMPL + }); + + [JoinName("SelfviewPosition")] + public JoinDataComplete SelfviewPosition = new JoinDataComplete( + new JoinData + { + JoinNumber = 211, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "advance selfview position", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ParticipantAudioMuteToggleStart")] + public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 500, + JoinSpan = 50 + }, + new JoinMetadata + { + Description = "Toggles the participant's audio mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ParticipantVideoMuteToggleStart")] + public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 800, + JoinSpan = 50 + }, + new JoinMetadata + { + Description = "Toggles the participant's video mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ParticipantPinToggleStart")] + public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 1100, + JoinSpan = 50 + }, + new JoinMetadata + { + Description = "Toggles the participant's pin status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + #endregion + + + + #region Analog + + [JoinName("MinutesBeforeMeetingStart")] + public JoinDataComplete MinutesBeforeMeetingStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 41, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Minutes before meeting start that a meeting is joinable", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraNumberSelect")] + public JoinDataComplete CameraNumberSelect = new JoinDataComplete( + new JoinData + { + JoinNumber = 60, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Number Select/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectoryRowCount")] + public JoinDataComplete DirectoryRowCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Row Count FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectorySelectRow")] + public JoinDataComplete DirectorySelectRow = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Select Row", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraPresetSelect")] + public JoinDataComplete CameraPresetSelect = new JoinDataComplete( + new JoinData + { + JoinNumber = 121, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Preset Select", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("ParticipantCount")] + public JoinDataComplete ParticipantCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 151, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Participant Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("Meeting Count Fb")] + public JoinDataComplete MeetingCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 161, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Meeting Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("VolumeLevel")] + public JoinDataComplete VolumeLevel = new JoinDataComplete( + new JoinData + { + JoinNumber = 174, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Level", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + #endregion + + + + #region Serials + + [JoinName("CurrentDialString")] + public JoinDataComplete CurrentDialString = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Dial String", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("PhoneString")] + public JoinDataComplete PhoneDialString = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Phone Dial String", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentCallName")] + public JoinDataComplete CurrentCallData = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Call Data - XSIG", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CallDirection")] + public JoinDataComplete CallDirection = new JoinDataComplete( + new JoinData + { + JoinNumber = 22, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Call Direction", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallName")] + public JoinDataComplete IncomingCallName = new JoinDataComplete( + new JoinData + { + JoinNumber = 51, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Incoming Call Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallNumber")] + public JoinDataComplete IncomingCallNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 52, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Incoming Call Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + + [JoinName("DirectorySearchString")] + public JoinDataComplete DirectorySearchString = new JoinDataComplete( + new JoinData + { + JoinNumber = 100, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Search String", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntries")] + public JoinDataComplete DirectoryEntries = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Entries - XSig, 255 entries", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("Schedule")] + public JoinDataComplete Schedule = new JoinDataComplete( + new JoinData + { + JoinNumber = 102, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Schedule Data - XSIG", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraPresetNames")] + public JoinDataComplete CameraPresetNames = new JoinDataComplete( + new JoinData + { + JoinNumber = 121, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Preset Names - XSIG, max of 15", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraLayoutStringFb")] + public JoinDataComplete CameraLayoutStringFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 141, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Layout Fb", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentParticipants")] + public JoinDataComplete CurrentParticipants = new JoinDataComplete( + new JoinData + { + JoinNumber = 151, + JoinSpan = 1 + }, + new JoinMetadata() + { + Description = "Current Participants XSig", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentSource")] + public JoinDataComplete CurrentSource = new JoinDataComplete( + new JoinData + { + JoinNumber = 201, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Source", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelfviewPositionFb")] + public JoinDataComplete SelfviewPositionFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 211, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "advance selfview position", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntrySelectedName")] + public JoinDataComplete DirectoryEntrySelectedName = new JoinDataComplete( + new JoinData + { + JoinNumber = 356, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Directory Entry Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntrySelectedNumber")] + public JoinDataComplete DirectoryEntrySelectedNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 357, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Directory Entry Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectorySelectedFolderName")] + public JoinDataComplete DirectorySelectedFolderName = new JoinDataComplete( + new JoinData + { + JoinNumber = 358, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Directory Folder Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + #endregion + + + public VideoCodecControllerJoinMap(uint joinStart) + : base(joinStart, typeof(VideoCodecControllerJoinMap)) + { + } + + public VideoCodecControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { + } + } +} diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingRecording.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingRecording.cs index 8aded9bf..b05362c3 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingRecording.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingRecording.cs @@ -19,5 +19,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces public interface IHasMeetingRecordingWithPrompt : IHasMeetingRecording { BoolFeedback RecordConsentPromptIsVisible { get; } + + /// + /// Used to agree or disagree to the meeting being recorded when prompted + /// + /// + void RecordingPromptAcknowledgement(bool agree); } } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasParticipants.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasParticipants.cs index 11c5f147..98c94bdc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasParticipants.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasParticipants.cs @@ -24,6 +24,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces /// /// void SetParticipantAsHost(int userId); + + /// + /// Admits a participant from the waiting room + /// + /// + void AdmitParticipantFromWaitingRoom(int userId); } /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index bb50b06a..7e2a13b5 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -518,10 +518,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void HandleCallRecordInfoStateUpdate(object sender, PropertyChangedEventArgs a) { - //Debug.Console(2, this, "**************** Status.Call.CallRecordInfo.PropertyChanged. PropertyName: {0} *********************************", a.PropertyName); if (a.PropertyName == "meetingIsBeingRecorded") { - //Debug.Console(2, this, "**************** Meeting Recording Info Updated. Recording: {0} **********************************", Status.Call.CallRecordInfo.meetingIsBeingRecorded); MeetingIsRecordingFeedback.FireUpdate(); var meetingInfo = new MeetingInfo(MeetingInfo.Id, @@ -536,10 +534,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom MeetingIsRecordingFeedback.BoolValue); MeetingInfo = meetingInfo; } - //else - //{ - // Debug.Console(2, this, "**************** Meeting Recording Info Updated. PropertyName: {0} *********************************", a.PropertyName); - //} } private void HandleCallStateUpdate(object sender, PropertyChangedEventArgs a) @@ -2374,6 +2368,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// 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; if (layoutsCodec != null) { @@ -2827,6 +2836,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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 #region IHasParticipantAudioMute Members @@ -3437,7 +3451,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom #endregion - #region IHasMeetingRecording Members + #region IHasMeetingRecordingWithPrompt Members public BoolFeedback MeetingIsRecordingFeedback { get; private set; } @@ -3445,14 +3459,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public BoolFeedback RecordConsentPromptIsVisible { get; private set; } + public void RecordingPromptAcknowledgement(bool agree) + { + SendText(string.Format("zCommand Agree Recording: {0}", agree ? "on" : "off")); + } + public void StartRecording() { - SendText(string.Format("Command Call Record Enable: on")); + SendText(string.Format("zCommand Call Record Enable: on")); } public void StopRecording() { - SendText(string.Format("Command Call Record Enable: off")); + SendText(string.Format("zCommand Call Record Enable: off")); } public void ToggleRecording() diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs index b977cfe3..48b2c039 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs @@ -295,7 +295,77 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Description = "Toggles the selfview pip size, (aka layout size)", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital - }); + }); + + [JoinName("StartRecording")] + public JoinDataComplete StartRecording = new JoinDataComplete( + new JoinData + { + JoinNumber = 241, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to start the Meeting Recording. FB high if meeting is currently recording", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("StopRecording")] + public JoinDataComplete StopRecording = new JoinDataComplete( + new JoinData + { + JoinNumber = 242, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to stop the Meeting Recording. FB high if meeting is currently NOT recording", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RecordConsentPromptIsVisible")] + public JoinDataComplete RecordConsentPromptIsVisible = new JoinDataComplete( + new JoinData + { + JoinNumber = 243, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "When high, indicates that the recording consent prompt is visible on the ZoomRoom UI", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RecordingPromptAgree")] + public JoinDataComplete RecordingPromptAgree = new JoinDataComplete( + new JoinData + { + JoinNumber = 244, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to agree to consent for meeting recording", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RecordingPromptDisagree")] + public JoinDataComplete RecordingPromptDisagree = new JoinDataComplete( + new JoinData + { + JoinNumber = 245, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to disagree to consent for meeting recording", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); //[JoinName("ParticipantAudioMuteToggleStart")] //public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( From b8442e7048a635d9eedeb2174dcbd4293e3d0872 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 18 May 2022 16:33:21 -0600 Subject: [PATCH 069/202] feat(essentials): Format update for command --- .../Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 7e2a13b5..73c1e8c5 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -3461,7 +3461,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void RecordingPromptAcknowledgement(bool agree) { - SendText(string.Format("zCommand Agree Recording: {0}", agree ? "on" : "off")); + 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() From 20beeb076a1dbc74cb40d56f17e53e900759818b Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Tue, 31 May 2022 17:19:56 -0500 Subject: [PATCH 070/202] add new interfaces for implementing PDUs added basic join map --- .../Bridges/JoinMaps/BasePduJoinMap.cs | 59 +++++++++++++++++++ .../Devices/PduInterfaces.cs | 39 ++++++++++++ .../PepperDash_Essentials_Core.csproj | 2 + 3 files changed, 100 insertions(+) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/BasePduJoinMap.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/BasePduJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/BasePduJoinMap.cs new file mode 100644 index 00000000..32ae92ac --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/BasePduJoinMap.cs @@ -0,0 +1,59 @@ +using System; + +namespace PepperDash.Essentials.Core.Bridges +{ + public class BasePduJoinMap : JoinMapBaseAdvanced + { + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "PDU Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("Online")] + public JoinDataComplete Online = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "PDU Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutletCount")] + public JoinDataComplete OutletCount = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Number of COntrolled Outlets", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("OutletName")] + public JoinDataComplete OutletName = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("OutletEnabled")] + public JoinDataComplete OutletEnabled = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Enabled", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutletPowerReboot")] + public JoinDataComplete OutletPowerReboot = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Power Reboot", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutletPowerOn")] + public JoinDataComplete OutletPowerOn = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Power On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutletPowerOff")] + public JoinDataComplete OutletPowerOff = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Power Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public BasePduJoinMap(uint joinStart) + :base(joinStart, typeof(BasePduJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + public BasePduJoinMap(uint joinStart, Type type) : base(joinStart, type) + { + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs new file mode 100644 index 00000000..2ca802a2 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash_Essentials_Core.Devices +{ + /// + /// Interface for any device that is able to control it'spower and has a configurable reboot time + /// + public interface IHasPowerReboot : IKeyName, IHasPowerControlWithFeedback + { + /// + /// Delay between power off and power on for reboot + /// + int PowerRebootTimeMs { get;} + + /// + /// Reboot outlet + /// + void PowerReboot(); + } + + /// + /// Interface for any device that contains a collection of IHasPowerReboot Devices + /// + public interface IHasControlledPowerOutlets : IKeyName + { + /// + /// Collection of IPduOutlets + /// + Dictionary PduOutlets { get; } + + /// + /// Count of PduOutlets + /// + int PduOutletsCount { get; } + + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 7123a150..2847b663 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -123,6 +123,7 @@ + @@ -203,6 +204,7 @@ + From 05f3a7eb2cbdcbf09f6222d247f8d5108c4ee37d Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Tue, 31 May 2022 17:46:13 -0500 Subject: [PATCH 071/202] UpdateJoinmap Names --- .../Bridges/JoinMaps/BasePduJoinMap.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/BasePduJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/BasePduJoinMap.cs index 32ae92ac..2ac56ff1 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/BasePduJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/BasePduJoinMap.cs @@ -2,7 +2,7 @@ namespace PepperDash.Essentials.Core.Bridges { - public class BasePduJoinMap : JoinMapBaseAdvanced + public class PduJoinMapBase : JoinMapBaseAdvanced { [JoinName("Name")] public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, @@ -24,9 +24,9 @@ namespace PepperDash.Essentials.Core.Bridges public JoinDataComplete OutletEnabled = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, new JoinMetadata { Description = "Outlet Enabled", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("OutletPowerReboot")] - public JoinDataComplete OutletPowerReboot = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata { Description = "Outlet Power Reboot", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("OutletPowerCycle")] + public JoinDataComplete OutletPowerCycle = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Power Cycle", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); [JoinName("OutletPowerOn")] public JoinDataComplete OutletPowerOn = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, @@ -42,8 +42,8 @@ namespace PepperDash.Essentials.Core.Bridges /// Constructor to use when instantiating this Join Map without inheriting from it /// /// Join this join map will start at - public BasePduJoinMap(uint joinStart) - :base(joinStart, typeof(BasePduJoinMap)) + public PduJoinMapBase(uint joinStart) + :base(joinStart, typeof(PduJoinMapBase)) { } @@ -52,7 +52,8 @@ namespace PepperDash.Essentials.Core.Bridges /// /// Join this join map will start at /// Type of the child join map - public BasePduJoinMap(uint joinStart, Type type) : base(joinStart, type) + public PduJoinMapBase(uint joinStart, Type type) + : base(joinStart, type) { } } From 86dfc395ec2dcffac5dd18a8cf3f1cdd74868283 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Tue, 31 May 2022 17:48:18 -0500 Subject: [PATCH 072/202] Rename IHasPowerReboot to IHasPowerCycle Update naming scheme to Cycle from Reboot --- .../PepperDashEssentialsBase/Devices/PduInterfaces.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs index 2ca802a2..4cdda3c6 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs @@ -7,17 +7,17 @@ namespace PepperDash_Essentials_Core.Devices /// /// Interface for any device that is able to control it'spower and has a configurable reboot time /// - public interface IHasPowerReboot : IKeyName, IHasPowerControlWithFeedback + public interface IHasPowerCycle : IKeyName, IHasPowerControlWithFeedback { /// /// Delay between power off and power on for reboot /// - int PowerRebootTimeMs { get;} + int PowerCycleTimeMs { get;} /// /// Reboot outlet /// - void PowerReboot(); + void PowerCycle(); } /// @@ -28,7 +28,7 @@ namespace PepperDash_Essentials_Core.Devices /// /// Collection of IPduOutlets /// - Dictionary PduOutlets { get; } + Dictionary PduOutlets { get; } /// /// Count of PduOutlets From 1cc37b752173750bd42821eca0a43d61b0ec16e5 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Thu, 2 Jun 2022 11:17:54 -0500 Subject: [PATCH 073/202] feature:Converted PduOutlets Dictionary to ReadOnlyDictionary feature:Removed redundant OutletCount property --- .../JoinMaps/{BasePduJoinMap.cs => PduJoinMapBase.cs} | 0 .../PepperDashEssentialsBase/Devices/PduInterfaces.cs | 8 ++------ .../PepperDash_Essentials_Core.csproj | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) rename essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/{BasePduJoinMap.cs => PduJoinMapBase.cs} (100%) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/BasePduJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/PduJoinMapBase.cs similarity index 100% rename from essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/BasePduJoinMap.cs rename to essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/PduJoinMapBase.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs index 4cdda3c6..0f3b3fbf 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/PduInterfaces.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Crestron.SimplSharp; using PepperDash.Core; using PepperDash.Essentials.Core; @@ -28,12 +29,7 @@ namespace PepperDash_Essentials_Core.Devices /// /// Collection of IPduOutlets /// - Dictionary PduOutlets { get; } - - /// - /// Count of PduOutlets - /// - int PduOutletsCount { get; } + ReadOnlyDictionary PduOutlets { get; } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 2847b663..c0903526 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -123,7 +123,7 @@ - + From 59b18d713bdb6cf3e47d36067d2658402d425641 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 8 Jun 2022 15:12:32 -0500 Subject: [PATCH 074/202] fix: corrects issue #951, c2nio incorrect factory reference --- .../Crestron IO/C2nIo/C2nIoController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/C2nIo/C2nIoController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/C2nIo/C2nIoController.cs index 0b70288f..f1f1891d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/C2nIo/C2nIoController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/C2nIo/C2nIoController.cs @@ -66,7 +66,7 @@ namespace PepperDash.Essentials.Core.CrestronIO #endregion } - public class C2NIoControllerFactory : EssentialsDeviceFactory + public class C2NIoControllerFactory : EssentialsDeviceFactory { public C2NIoControllerFactory() { From 96e3d52b95543e46be0b88656e6de28e3b22a1be Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 09:43:59 -0400 Subject: [PATCH 075/202] Switch DMPS units to only wait until devices are registered before continuing. No need to wait for devices to be activated. --- PepperDashEssentials/ControlSystem.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index 53ea9e13..dd8f3d5a 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -53,14 +53,14 @@ namespace PepperDash.Essentials // to allow any HD-BaseT DM endpoints to register first. if (Global.ControlSystemIsDmpsType) { - Debug.Console(2, "******************* InitializeSystem() Entering **********************"); + Debug.Console(1, "******************* InitializeSystem() Entering **********************"); _initializeEvent = new CEvent(); - DeviceManager.AllDevicesActivated += (o, a) => + DeviceManager.AllDevicesRegistered += (o, a) => { _initializeEvent.Set(); - Debug.Console(2, "******************* InitializeSystem() Exiting **********************"); + Debug.Console(1, "******************* InitializeSystem() Exiting **********************"); }; _initializeEvent.Wait(30000); From dfc0915fe0edff27d76a3bece126065649bb34fd Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 09:56:40 -0400 Subject: [PATCH 076/202] Adds DM switcher name to bridge --- .../Bridges/JoinMaps/DmChassisControllerJoinMap.cs | 4 ++++ .../Essentials_DM/Chassis/DmChassisController.cs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmChassisControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmChassisControllerJoinMap.cs index 3582e6cf..114a8a9d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmChassisControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmChassisControllerJoinMap.cs @@ -24,6 +24,10 @@ namespace PepperDash.Essentials.Core.Bridges JoinType = eJoinType.Digital }); + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "DM Chassis Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("SystemId")] public JoinDataComplete SystemId = new JoinDataComplete(new JoinData { JoinNumber = 10, JoinSpan = 1 }, new JoinMetadata { Description = "DM Chassis SystemId Get/Set/Trigger/", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.DigitalAnalog }); diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs index ef7fc577..60ef9d69 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs @@ -1482,6 +1482,8 @@ namespace PepperDash.Essentials.DM LinkChassisToApi(trilist, joinMap); + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = this.Name; + // Link up inputs & outputs for (uint i = 1; i <= Chassis.NumberOfOutputs; i++) { From 60b6cea69750745f128f3e7e45a158b4a3fc7f22 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 10:13:02 -0400 Subject: [PATCH 077/202] Adds digital audio output volume control for DMPS to bridge --- .../DmpsAudioOutputControllerJoinMap.cs | 4 + .../Chassis/DmpsAudioOutputController.cs | 116 ++++++++++--- .../Chassis/DmpsRoutingController.cs | 156 ++++++++++-------- 3 files changed, 179 insertions(+), 97 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmpsAudioOutputControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmpsAudioOutputControllerJoinMap.cs index c7d5c0e5..a6100700 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmpsAudioOutputControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmpsAudioOutputControllerJoinMap.cs @@ -17,6 +17,10 @@ namespace PepperDash.Essentials.Core.Bridges public JoinDataComplete MixerPresetRecall = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, new JoinMetadata { Description = "Mixer Preset Recall Set", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("MixerEqPresetRecall")] + public JoinDataComplete MixerEqPresetRecall = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Mixer Eq Preset Recall Set", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("MasterVolumeMuteOn")] public JoinDataComplete MasterVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, new JoinMetadata { Description = "Master Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs index 751c1a5a..60943270 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs @@ -33,36 +33,44 @@ namespace PepperDash.Essentials.DM : base(key, name) { OutputCard = card; - OutputCard.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange); + SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster); + if (card is Card.Dmps3ProgramOutput) { - MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, (card as Card.Dmps3ProgramOutput).OutputMixer); - SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source); - MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster); + var output = card as Card.Dmps3ProgramOutput; + MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(card, eDmpsLevelType.Master, output.OutputMixer, output.OutputEqualizer); Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1); Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2); } else if (card is Card.Dmps3Aux1Output) { - MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, (card as Card.Dmps3Aux1Output).OutputMixer); - SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source); - MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster); + var output = card as Card.Dmps3Aux1Output; + MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(card, eDmpsLevelType.Master, output.OutputMixer, output.OutputEqualizer); Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2); } else if (card is Card.Dmps3Aux2Output) { - MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, (card as Card.Dmps3Aux2Output).OutputMixer); - SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source); - MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster); + var output = card as Card.Dmps3Aux2Output; + MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(card, eDmpsLevelType.Master, output.OutputMixer, output.OutputEqualizer); Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1); } - else //Digital Outputs + else if (card is Card.Dmps3DigitalMixOutput) { - MasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Master); - SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source); - MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster); + var output = card as Card.Dmps3DigitalMixOutput; + MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, output.OutputMixer); + } + else if (card is Card.Dmps3HdmiOutput) + { + var output = card as Card.Dmps3HdmiOutput; + MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, output.OutputMixer); + } + else if (card is Card.Dmps3DmOutput) + { + var output = card as Card.Dmps3DmOutput; + MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, output.OutputMixer); } } @@ -185,6 +193,11 @@ namespace PepperDash.Essentials.DM { trilist.SetUShortSigAction(joinMap.MixerPresetRecall.JoinNumber, mixer.RecallPreset); } + var eq = MasterVolumeLevel as DmpsAudioOutputWithMixerAndEq; + if (eq != null) + { + trilist.SetUShortSigAction(joinMap.MixerEqPresetRecall.JoinNumber, eq.RecallEqPreset); + } } if (SourceVolumeLevel != null) @@ -234,11 +247,27 @@ namespace PepperDash.Essentials.DM } } + public class DmpsAudioOutputWithMixerAndEq : DmpsAudioOutputWithMixer + { + private CrestronControlSystem.Dmps3OutputEqualizer Eq; + public DmpsAudioOutputWithMixerAndEq(Card.Dmps3OutputBase output, eDmpsLevelType type, CrestronControlSystem.Dmps3OutputMixer mixer, CrestronControlSystem.Dmps3OutputEqualizer eq) + : base(output, type, mixer) + { + Eq = eq; + } + + public void RecallEqPreset(ushort preset) + { + Eq.PresetNumber.UShortValue = preset; + Eq.RecallPreset(); + } + } + public class DmpsAudioOutputWithMixer : DmpsAudioOutput { - CrestronControlSystem.Dmps3OutputMixerWithMonoAndStereo Mixer; + IDmps3OutputMixer Mixer; - public DmpsAudioOutputWithMixer(Card.Dmps3OutputBase output, eDmpsLevelType type, CrestronControlSystem.Dmps3OutputMixerWithMonoAndStereo mixer) + public DmpsAudioOutputWithMixer(Card.Dmps3OutputBase output, eDmpsLevelType type, IDmps3OutputMixer mixer) : base(output, type) { Mixer = mixer; @@ -266,23 +295,47 @@ namespace PepperDash.Essentials.DM public void RecallPreset(ushort preset) { - Debug.Console(1, "DMPS Recalling Preset {0}", preset); - Mixer.PresetNumber.UShortValue = preset; - Mixer.RecallPreset(); + if (Mixer is CrestronControlSystem.Dmps3OutputMixer) + { + var presetMixer = Mixer as CrestronControlSystem.Dmps3OutputMixer; + Debug.Console(1, "DMPS Recalling Preset {0}", preset); + presetMixer.PresetNumber.UShortValue = preset; + presetMixer.RecallPreset(); + + //Recall startup volume for main volume level as DMPS3(non-4K) presets don't affect the main volume + RecallStartupVolume(); + } + else if (Mixer is CrestronControlSystem.Dmps3AttachableOutputMixer) + { + var presetMixer = Mixer as CrestronControlSystem.Dmps3AttachableOutputMixer; + Debug.Console(1, "DMPS Recalling Preset {0}", preset); + presetMixer.PresetNumber.UShortValue = preset; + presetMixer.RecallPreset(); + } + + } + + public void RecallStartupVolume() + { + ushort startupVol = Mixer.StartupVolumeFeedback.UShortValue; + //Reset startup vol due to bug on DMPS3 where getting the value from above method clears the startup volume + Mixer.StartupVolume.UShortValue = startupVol; + Debug.Console(1, "DMPS Recalling {0} Startup Volume {1}", Output.Name, startupVol); + SetVolume(startupVol); + MuteOff(); } } public class DmpsAudioOutput : IBasicVolumeWithFeedback { - Card.Dmps3OutputBase Output; - eDmpsLevelType Type; - UShortInputSig Level; - + private UShortInputSig Level; + protected Card.Dmps3OutputBase Output; private bool EnableVolumeSend; private ushort VolumeLevelInput; protected short MinLevel { get; set; } protected short MaxLevel { get; set; } + public eDmpsLevelType Type { get; private set; } public BoolFeedback MuteFeedback { get; private set; } public IntFeedback VolumeLevelFeedback { get; private set; } public IntFeedback VolumeLevelScaledFeedback { get; private set; } @@ -411,10 +464,13 @@ namespace PepperDash.Essentials.DM public void SetVolumeScaled(ushort level) { Debug.Console(2, Debug.ErrorLogLevel.None, "Scaling DMPS volume:{0} level:{1} min:{2} max:{3}", Output.Name, level.ToString(), MinLevel.ToString(), MaxLevel.ToString()); - VolumeLevelInput = (ushort)(level * (MaxLevel - MinLevel) / ushort.MaxValue + MinLevel); - if (EnableVolumeSend == true) + if (ushort.MaxValue + MinLevel != 0) { - Level.UShortValue = VolumeLevelInput; + VolumeLevelInput = (ushort)(level * (MaxLevel - MinLevel) / ushort.MaxValue + MinLevel); + if (EnableVolumeSend == true) + { + Level.UShortValue = VolumeLevelInput; + } } } @@ -422,7 +478,13 @@ namespace PepperDash.Essentials.DM { short signedLevel = (short)level; Debug.Console(2, Debug.ErrorLogLevel.None, "Scaling DMPS volume:{0} feedback:{1} min:{2} max:{3}", Output.Name, signedLevel.ToString(), MinLevel.ToString(), MaxLevel.ToString()); - return (ushort)((signedLevel - MinLevel) * ushort.MaxValue / (MaxLevel - MinLevel)); + + if (MaxLevel - MinLevel != 0) + { + return (ushort)((signedLevel - MinLevel) * ushort.MaxValue / (MaxLevel - MinLevel)); + } + else + return (ushort)MinLevel; } public void SendScaledVolume(bool pressRelease) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index f6592699..22dfc195 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -481,69 +481,76 @@ namespace PepperDash.Essentials.DM { foreach (var card in Dmps.SwitcherOutputs) { - Debug.Console(1, this, "Output Card Type: {0}", card.CardInputOutputType); - - var outputCard = card as DMOutput; - - if (outputCard == null) + try { - Debug.Console(1, this, "Output card {0} is not a DMOutput", card.CardInputOutputType); - continue; - } + Debug.Console(1, this, "Output Card Type: {0}", card.CardInputOutputType); - Debug.Console(1, this, "Adding Output Card Number {0} Type: {1}", outputCard.Number, outputCard.CardInputOutputType.ToString()); - VideoOutputFeedbacks[outputCard.Number] = new IntFeedback(() => - { - if (outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number; } - return 0; - ; - }); - AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() => - { - try + var outputCard = card as DMOutput; + + if (outputCard == null) { - if (outputCard.AudioOutFeedback != null) - { - return (ushort) outputCard.AudioOutFeedback.Number; - } + Debug.Console(1, this, "Output card {0} is not a DMOutput", card.CardInputOutputType); + continue; + } + + Debug.Console(1, this, "Adding Output Card Number {0} Type: {1}", outputCard.Number, outputCard.CardInputOutputType.ToString()); + VideoOutputFeedbacks[outputCard.Number] = new IntFeedback(() => + { + if (outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number; } return 0; - } - catch (NotSupportedException) + ; + }); + AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() => { - return (ushort) outputCard.AudioOutSourceFeedback; - } - }); + try + { + if (outputCard.AudioOutFeedback != null) + { + return (ushort)outputCard.AudioOutFeedback.Number; + } + return 0; + } + catch (NotSupportedException) + { + return (ushort)outputCard.AudioOutSourceFeedback; + } + }); - OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() => + OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() => + { + if (outputCard.NameFeedback != null && outputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue)) + { + Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue); + return outputCard.NameFeedback.StringValue; + } + return ""; + }); + + OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => + { + if (outputCard.VideoOutFeedback != null && outputCard.VideoOutFeedback.NameFeedback != null) + { + return outputCard.VideoOutFeedback.NameFeedback.StringValue; + } + return NoRouteText; + }); + OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => + { + if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null) + { + return outputCard.AudioOutFeedback.NameFeedback.StringValue; + } + return NoRouteText; + }); + + OutputEndpointOnlineFeedbacks[outputCard.Number] = new BoolFeedback(() => outputCard.EndpointOnlineFeedback); + + AddOutputCard(outputCard.Number, outputCard); + } + catch (Exception ex) { - if (outputCard.NameFeedback != null && outputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue)) - { - Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue); - return outputCard.NameFeedback.StringValue; - } - return ""; - }); - - OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => - { - if (outputCard.VideoOutFeedback != null && outputCard.VideoOutFeedback.NameFeedback != null) - { - return outputCard.VideoOutFeedback.NameFeedback.StringValue; - } - return NoRouteText; - }); - OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => - { - if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null) - { - return outputCard.AudioOutFeedback.NameFeedback.StringValue; - } - return NoRouteText; - }); - - OutputEndpointOnlineFeedbacks[outputCard.Number] = new BoolFeedback(() => outputCard.EndpointOnlineFeedback); - - AddOutputCard(outputCard.Number, outputCard); + Debug.LogError(Debug.ErrorLogLevel.Error, string.Format("DMPS Controller exception creating output card: {0}", ex)); + } } } @@ -697,6 +704,9 @@ namespace PepperDash.Essentials.DM var cecPort = hdmiOutputCard.HdmiOutputPort; AddHdmiOutputPort(number, cecPort); + + var audioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number), string.Format("Hdmi Audio Output {0}", number), outputCard as Card.Dmps3HdmiOutput); + DeviceManager.AddDevice(audioOutput); } else if (outputCard is Card.Dmps3HdmiOutputBackend) { @@ -709,6 +719,9 @@ namespace PepperDash.Essentials.DM else if (outputCard is Card.Dmps3DmOutput) { AddDmOutputPort(number); + + var audioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number), string.Format("Dm Audio Output {0}", number), outputCard as Card.Dmps3DmOutput); + DeviceManager.AddDevice(audioOutput); } else if (outputCard is Card.Dmps3DmOutputBackend) { @@ -727,22 +740,22 @@ namespace PepperDash.Essentials.DM switch (outputCard.CardInputOutputType) { case eCardInputOutputType.Dmps3Aux1Output: - { - AddAudioOnlyOutputPort(number, "Aux1"); + { + AddAudioOnlyOutputPort(number, "Aux1"); - var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux1Output); + var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux1Output); - DeviceManager.AddDevice(aux1Output); - } + DeviceManager.AddDevice(aux1Output); + } break; case eCardInputOutputType.Dmps3Aux2Output: - { - AddAudioOnlyOutputPort(number, "Aux2"); + { + AddAudioOnlyOutputPort(number, "Aux2"); - var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux2Output); + var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux2Output); - DeviceManager.AddDevice(aux2Output); - } + DeviceManager.AddDevice(aux2Output); + } break; } } @@ -766,6 +779,10 @@ namespace PepperDash.Essentials.DM { AddAudioOnlyOutputPort(number, "Dialer"); } + else if (outputCard is Card.Dmps3AecOutput) + { + AddAudioOnlyOutputPort(number, "Aec"); + } else if (outputCard is Card.Dmps3DigitalMixOutput) { if (number == (uint)CrestronControlSystem.eDmps34K250COutputs.Mix1 @@ -776,10 +793,9 @@ namespace PepperDash.Essentials.DM || number == (uint)CrestronControlSystem.eDmps34K300COutputs.Mix2 || number == (uint)CrestronControlSystem.eDmps34K350COutputs.Mix2) AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps34K250COutputs.Mix2.ToString()); - } - else if (outputCard is Card.Dmps3AecOutput) - { - AddAudioOnlyOutputPort(number, "Aec"); + + var audioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number % 2 + 1), string.Format("Digital Audio Output {0}", number % 2 + 1), outputCard as Card.Dmps3DigitalMixOutput); + DeviceManager.AddDevice(audioOutput); } else { From b26e1b97aa35f32ecc1cd2325f38b58a75e1b3e5 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 10:23:51 -0400 Subject: [PATCH 078/202] Removes redundant check for DMPS-4K type. Property exists elsewhere --- .../Devices/DeviceManager.cs | 12 +++++++++++ .../Chassis/DmpsRoutingController.cs | 20 +++++++------------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs index df864550..57bf2287 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs @@ -14,6 +14,7 @@ namespace PepperDash.Essentials.Core public static class DeviceManager { public static event EventHandler AllDevicesActivated; + public static event EventHandler AllDevicesRegistered; private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection(); private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true); @@ -57,6 +58,8 @@ namespace PepperDash.Essentials.Core { try { + OnAllDevicesRegistered(); + DeviceCriticalSection.Enter(); AddDeviceEnabled = false; // PreActivate all devices @@ -129,6 +132,15 @@ namespace PepperDash.Essentials.Core } } + private static void OnAllDevicesRegistered() + { + var handler = AllDevicesRegistered; + if (handler != null) + { + handler(null, new EventArgs()); + } + } + /// /// Calls activate on all Device class items /// diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index 22dfc195..5c03e8e9 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -26,13 +26,10 @@ namespace PepperDash.Essentials.DM public CrestronControlSystem Dmps { get; set; } public ISystemControl SystemControl { get; private set; } public bool? EnableRouting { get; private set; } - - //Check if DMPS is a DMPS3-4K type for endpoint creation - public bool Dmps4kType { get; private set; } //IroutingNumericEvent public event EventHandler NumericSwitchChange; - + //Feedback for DMPS System Control public BoolFeedback SystemPowerOnFeedback { get; private set; } public BoolFeedback SystemPowerOffFeedback { get; private set; } @@ -123,14 +120,13 @@ namespace PepperDash.Essentials.DM /// public DmpsRoutingController(string key, string name, ISystemControl systemControl) : base(key, name) - { + { Dmps = Global.ControlSystem; - + switch (systemControl.SystemControlType) { case eSystemControlType.Dmps34K150CSystemControl: SystemControl = systemControl as Dmps34K150CSystemControl; - Dmps4kType = true; SystemPowerOnFeedback = new BoolFeedback(() => { return true; }); SystemPowerOffFeedback = new BoolFeedback(() => { return false; }); break; @@ -139,13 +135,11 @@ namespace PepperDash.Essentials.DM case eSystemControlType.Dmps34K300CSystemControl: case eSystemControlType.Dmps34K350CSystemControl: SystemControl = systemControl as Dmps34K300CSystemControl; - Dmps4kType = true; SystemPowerOnFeedback = new BoolFeedback(() => { return true; }); SystemPowerOffFeedback = new BoolFeedback(() => { return false; }); break; default: SystemControl = systemControl as Dmps3SystemControl; - Dmps4kType = false; SystemPowerOnFeedback = new BoolFeedback(() => { return ((Dmps3SystemControl)SystemControl).SystemPowerOnFeedBack.BoolValue; @@ -156,7 +150,7 @@ namespace PepperDash.Essentials.DM }); break; } - Debug.Console(1, this, "DMPS Type = {0}, 4K Type = {1}", systemControl.SystemControlType, Dmps4kType); + Debug.Console(1, this, "DMPS Type = {0}, 4K Type = {1}", systemControl.SystemControlType, Global.ControlSystemIsDmps4kType); InputPorts = new RoutingPortCollection(); OutputPorts = new RoutingPortCollection(); @@ -406,7 +400,7 @@ namespace PepperDash.Essentials.DM private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap) { - if (Dmps4kType) + if (Global.ControlSystemIsDmps4kType) { //DMPS-4K audio inputs 1-5 are aux inputs for (uint i = 1; i <= 5; i++) @@ -427,12 +421,12 @@ namespace PepperDash.Essentials.DM trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); } - if (InputNameFeedbacks.ContainsKey(ioSlot) && InputNameFeedbacks[ioSlot] != null) + if (InputNameFeedbacks.ContainsKey(ioSlot) && InputNameFeedbacks[ioSlot] != null) { InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputVideoNames.JoinNumber + ioSlotJoin]); - if (Dmps4kType) + if (Global.ControlSystemIsDmps4kType) { //DMPS-4K Audio Inputs are offset by 5 InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin + 5]); From 03e4c913ac5824ef839a90a54ca0a09de11a38a9 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 10:24:19 -0400 Subject: [PATCH 079/202] Adds HD-MD-8xn switcher type support --- .../Chassis/HdMd8xNController.cs | 516 ++++++++++++++++++ 1 file changed, 516 insertions(+) create mode 100644 essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs new file mode 100644 index 00000000..00e3b974 --- /dev/null +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs @@ -0,0 +1,516 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.DM; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.DM.Config; +using Crestron.SimplSharpPro.DM.Cards; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Config; + + +namespace PepperDash.Essentials.DM.Chassis +{ + [Description("Wrapper class for all HdMd8xN switchers")] + public class HdMd8xNController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback + { + private HdMd8xN _Chassis; + + public event EventHandler NumericSwitchChange; + + public Dictionary InputNames { get; set; } + public Dictionary OutputNames { get; set; } + + public RoutingPortCollection InputPorts { get; private set; } + public RoutingPortCollection OutputPorts { get; private set; } + + public FeedbackCollection VideoInputSyncFeedbacks { get; private set; } + public FeedbackCollection VideoOutputRouteFeedbacks { get; private set; } + public FeedbackCollection AudioOutputRouteFeedbacks { get; private set; } + public FeedbackCollection InputNameFeedbacks { get; private set; } + public FeedbackCollection OutputNameFeedbacks { get; private set; } + public FeedbackCollection OutputVideoRouteNameFeedbacks { get; private set; } + public FeedbackCollection OutputAudioRouteNameFeedbacks { get; private set; } + public StringFeedback DeviceNameFeedback { get; private set; } + + #region Constructor + + public HdMd8xNController(string key, string name, HdMd8xN chassis, + DMChassisPropertiesConfig props) + : base(key, name, chassis) + { + _Chassis = chassis; + Name = name; + _Chassis.EnableAudioBreakaway.BoolValue = true; + + if (props == null) + { + Debug.Console(1, this, "HdMd8xNController properties are null, failed to build the device"); + return; + } + + InputNames = new Dictionary(); + if (props.InputNames != null) + { + InputNames = props.InputNames; + } + OutputNames = new Dictionary(); + if (props.OutputNames != null) + { + OutputNames = props.OutputNames; + } + + DeviceNameFeedback = new StringFeedback(()=> Name); + + VideoInputSyncFeedbacks = new FeedbackCollection(); + VideoOutputRouteFeedbacks = new FeedbackCollection(); + AudioOutputRouteFeedbacks = new FeedbackCollection(); + InputNameFeedbacks = new FeedbackCollection(); + OutputNameFeedbacks = new FeedbackCollection(); + OutputVideoRouteNameFeedbacks = new FeedbackCollection(); + OutputAudioRouteNameFeedbacks = new FeedbackCollection(); + + InputPorts = new RoutingPortCollection(); + OutputPorts = new RoutingPortCollection(); + + //Inputs - should always be 8 audio/video inputs + for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) + { + try + { + var index = i; + if (!InputNames.ContainsKey(index)) + { + InputNames.Add(index, string.Format("Input{0}", index)); + } + string inputName = InputNames[index]; + _Chassis.Inputs[index].Name.StringValue = inputName; + + + InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, _Chassis.Inputs[index], this) + { + FeedbackMatchObject = _Chassis.Inputs[index] + }); + + VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[index].VideoDetectedFeedback.BoolValue)); + InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[index].NameFeedback.StringValue)); + } + catch (Exception ex) + { + ErrorLog.Error("Exception creating input {0} on HD-MD8xN Chassis: {1}", i, ex); + } + } + + //Outputs. Either 2 outputs (1 audio, 1 audio/video) for HD-MD8x1 or 4 outputs (2 audio, 2 audio/video) for HD-MD8x2 + for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) + { + try + { + var index = i; + if (!OutputNames.ContainsKey(index)) + { + OutputNames.Add(index, string.Format("Output{0}", index)); + } + string outputName = OutputNames[index]; + _Chassis.Outputs[index].Name.StringValue = outputName; + + OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, _Chassis.Outputs[index], this) + { + FeedbackMatchObject = _Chassis.Outputs[index] + }); + + OutputNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].NameFeedback.StringValue)); + VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback == null ? 0 : (int)_Chassis.Outputs[index].VideoOutFeedback.Number)); + AudioOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => _Chassis.Outputs[index].AudioOutFeedback == null ? 0 : (int)_Chassis.Outputs[index].AudioOutFeedback.Number)); + OutputVideoRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback == null ? "None" : _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue)); + OutputAudioRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].AudioOutFeedback == null ? "None" : _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue)); + } + catch (Exception ex) + { + ErrorLog.Error("Exception creating output {0} on HD-MD8xN Chassis: {1}", i, ex); + } + } + + _Chassis.DMInputChange += Chassis_DMInputChange; + _Chassis.DMOutputChange += Chassis_DMOutputChange; + + AddPostActivationAction(AddFeedbackCollections); + } + #endregion + + #region Methods + + /// + /// Raise an event when the status of a switch object changes. + /// + /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType + private void OnSwitchChange(RoutingNumericEventArgs e) + { + var newEvent = NumericSwitchChange; + if (newEvent != null) newEvent(this, e); + } + + #region PostActivate + + public void AddFeedbackCollections() + { + AddFeedbackToList(DeviceNameFeedback); + AddCollectionsToList(VideoInputSyncFeedbacks); + AddCollectionsToList(VideoOutputRouteFeedbacks, AudioOutputRouteFeedbacks); + AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputVideoRouteNameFeedbacks, OutputAudioRouteNameFeedbacks); + } + + #endregion + + #region FeedbackCollection Methods + + //Add arrays of collections + public void AddCollectionsToList(params FeedbackCollection[] newFbs) + { + foreach (FeedbackCollection fbCollection in newFbs) + { + foreach (var item in newFbs) + { + AddCollectionToList(item); + } + } + } + public void AddCollectionsToList(params FeedbackCollection[] newFbs) + { + foreach (FeedbackCollection fbCollection in newFbs) + { + foreach (var item in newFbs) + { + AddCollectionToList(item); + } + } + } + + public void AddCollectionsToList(params FeedbackCollection[] newFbs) + { + foreach (FeedbackCollection fbCollection in newFbs) + { + foreach (var item in newFbs) + { + AddCollectionToList(item); + } + } + } + + //Add Collections + public void AddCollectionToList(FeedbackCollection newFbs) + { + foreach (var f in newFbs) + { + if (f == null) continue; + + AddFeedbackToList(f); + } + } + + public void AddCollectionToList(FeedbackCollection newFbs) + { + foreach (var f in newFbs) + { + if (f == null) continue; + + AddFeedbackToList(f); + } + } + + public void AddCollectionToList(FeedbackCollection newFbs) + { + foreach (var f in newFbs) + { + if (f == null) continue; + + AddFeedbackToList(f); + } + } + + //Add Individual Feedbacks + public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback newFb) + { + if (newFb == null) return; + + if (!Feedbacks.Contains(newFb)) + { + Feedbacks.Add(newFb); + } + } + + #endregion + + #region IRouting Members + + public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType sigType) + { + var input = inputSelector as DMInput; + var output = outputSelector as DMOutput; + Debug.Console(2, this, "ExecuteSwitch: input={0} output={1} sigType={2}", input, output, sigType.ToString()); + + if (output == null) + { + Debug.Console(0, this, "Unable to make switch. Output selector is not DMOutput"); + return; + } + + if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) + { + _Chassis.VideoEnter.BoolValue = true; + if (output != null) + { + output.VideoOut = input; + } + } + + if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) + { + _Chassis.AudioEnter.BoolValue = true; + if (output != null) + { + output.AudioOut = input; + } + } + } + + #endregion + + #region IRoutingNumeric Members + + public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType signalType) + { + + var input = inputSelector == 0 ? null : _Chassis.Inputs[inputSelector]; + var output = _Chassis.Outputs[outputSelector]; + + Debug.Console(2, this, "ExecuteNumericSwitch: input={0} output={1}", input, output); + + ExecuteSwitch(input, output, signalType); + } + + #endregion + + #endregion + + #region Bridge Linking + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new DmChassisControllerJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } + + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = "DM Switcher"; + + for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) + { + var joinIndex = i - 1; + var input = i; + //Digital + VideoInputSyncFeedbacks[InputNames[input]].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + joinIndex]); + + //Serial + InputNameFeedbacks[InputNames[input]].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + joinIndex]); + } + + for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) + { + var joinIndex = i - 1; + var output = i; + //Analog + VideoOutputRouteFeedbacks[OutputNames[output]].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + joinIndex]); + trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + joinIndex, (a) => ExecuteNumericSwitch(a, (ushort)output, eRoutingSignalType.Video)); + AudioOutputRouteFeedbacks[OutputNames[output]].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + joinIndex]); + trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + joinIndex, (a) => ExecuteNumericSwitch(a, (ushort)output, eRoutingSignalType.Audio)); + + //Serial + OutputNameFeedbacks[OutputNames[output]].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + joinIndex]); + OutputVideoRouteNameFeedbacks[OutputNames[output]].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + joinIndex]); + OutputAudioRouteNameFeedbacks[OutputNames[output]].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + joinIndex]); + } + + _Chassis.OnlineStatusChange += Chassis_OnlineStatusChange; + + trilist.OnlineStatusChange += (d, args) => + { + if (!args.DeviceOnLine) return; + }; + } + + + #endregion + + #region Events + + void Chassis_OnlineStatusChange(Crestron.SimplSharpPro.GenericBase currentDevice, Crestron.SimplSharpPro.OnlineOfflineEventArgs args) + { + IsOnline.FireUpdate(); + + if (!args.DeviceOnLine) return; + + foreach (var feedback in Feedbacks) + { + feedback.FireUpdate(); + } + } + + void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args) + { + switch (args.EventId) + { + case DMOutputEventIds.VideoOutEventId: + { + var output = args.Number; + var inputNumber = _Chassis.Outputs[output].VideoOutFeedback == null ? 0 : _Chassis.Outputs[output].VideoOutFeedback.Number; + + var outputName = OutputNames[output]; + + var feedback = VideoOutputRouteFeedbacks[outputName]; + + if (feedback == null) + { + return; + } + var inPort = InputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.Outputs[output].VideoOutFeedback); + var outPort = OutputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.Outputs[output]); + + feedback.FireUpdate(); + OnSwitchChange(new RoutingNumericEventArgs(output, inputNumber, outPort, inPort, eRoutingSignalType.Video)); + break; + } + case DMOutputEventIds.AudioOutEventId: + { + var output = args.Number; + var inputNumber = _Chassis.Outputs[output].AudioOutFeedback == null ? 0 : _Chassis.Outputs[output].AudioOutFeedback.Number; + + var outputName = OutputNames[output]; + + var feedback = AudioOutputRouteFeedbacks[outputName]; + + if (feedback == null) + { + return; + } + var inPort = InputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.Outputs[output].AudioOutFeedback); + var outPort = OutputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.Outputs[output]); + + feedback.FireUpdate(); + OnSwitchChange(new RoutingNumericEventArgs(output, inputNumber, outPort, inPort, eRoutingSignalType.Audio)); + break; + } + case DMOutputEventIds.OutputNameEventId: + case DMOutputEventIds.NameFeedbackEventId: + { + Debug.Console(1, this, "Event ID {0}: Updating name feedbacks.", args.EventId); + Debug.Console(1, this, "Output {0} Name {1}", args.Number, + _Chassis.Outputs[args.Number].NameFeedback.StringValue); + foreach (var item in OutputNameFeedbacks) + { + item.FireUpdate(); + } + break; + } + default: + { + Debug.Console(1, this, "Unhandled DM Output Event ID {0}", args.EventId); + break; + } + } + } + + void Chassis_DMInputChange(Switch device, DMInputEventArgs args) + { + switch (args.EventId) + { + case DMInputEventIds.VideoDetectedEventId: + { + Debug.Console(1, this, "Event ID {0}: Updating VideoInputSyncFeedbacks", args.EventId); + foreach (var item in VideoInputSyncFeedbacks) + { + item.FireUpdate(); + } + break; + } + case DMInputEventIds.InputNameFeedbackEventId: + case DMInputEventIds.InputNameEventId: + case DMInputEventIds.NameFeedbackEventId: + { + Debug.Console(1, this, "Event ID {0}: Updating name feedbacks.", args.EventId); + Debug.Console(1, this, "Input {0} Name {1}", args.Number, + _Chassis.Inputs[args.Number].NameFeedback.StringValue); + foreach (var item in InputNameFeedbacks) + { + item.FireUpdate(); + } + break; + } + default: + { + Debug.Console(1, this, "Unhandled DM Input Event ID {0}", args.EventId); + break; + } + } + } + + #endregion + + #region Factory + + public class HdMd8xNControllerFactory : EssentialsDeviceFactory + { + public HdMd8xNControllerFactory() + { + TypeNames = new List() { "hdmd8x2", "hdmd8x1" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new HD-MD-8xN Device"); + + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + + var type = dc.Type.ToLower(); + var control = props.Control; + var ipid = control.IpIdInt; + + switch (type) + { + case ("hdmd8x2"): + return new HdMd8xNController(dc.Key, dc.Name, new HdMd8x2(ipid, Global.ControlSystem), props); + case ("hdmd8x1"): + return new HdMd8xNController(dc.Key, dc.Name, new HdMd8x1(ipid, Global.ControlSystem), props); + default: + return null; + } + } + } + + #endregion + + + + } +} \ No newline at end of file From 50e9a7935fa4de917a26dd67dabcc8cb50a10c3f Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 10:25:06 -0400 Subject: [PATCH 080/202] Adds HD-MD-8xn switcher type support --- .../Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj index cef61b1a..ea3dbd5d 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -100,6 +100,7 @@ + From 1a5d4896e168f6ee93e70adeb5eced1d3174cde8 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 10:43:29 -0400 Subject: [PATCH 081/202] Fixes online feedback for DM endpoints that are attached to a 3 series DM chassis or a DMPS-4K unit. --- .../Crestron/CrestronGenericBaseDevice.cs | 18 ++- .../DmpsInternalVirtualDmTxController.cs | 25 ++-- .../Chassis/DmpsRoutingController.cs | 12 ++ .../Chassis/HdMd8xNController.cs | 2 +- .../Endpoints/Receivers/DmRmcHelper.cs | 120 +++++++++++------- .../Endpoints/Transmitters/DmTxHelpers.cs | 41 +++++- 6 files changed, 155 insertions(+), 63 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs index b7534087..f4d13d4e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs @@ -20,7 +20,7 @@ namespace PepperDash.Essentials.Core /// public FeedbackCollection Feedbacks { get; private set; } - public BoolFeedback IsOnline { get; private set; } + public BoolFeedback IsOnline { get; set; } public BoolFeedback IsRegistered { get; private set; } public StringFeedback IpConnectionsText { get; private set; } @@ -73,11 +73,14 @@ namespace PepperDash.Essentials.Core { //Debug.Console(1, this, " Does not require registration. Skipping"); - var response = Hardware.RegisterWithLogging(Key); - if (response != eDeviceRegistrationUnRegistrationResponse.Success) + if (Hardware.Registerable && !Hardware.Registered) { - //Debug.Console(0, this, "ERROR: Cannot register Crestron device: {0}", response); - return false; + var response = Hardware.RegisterWithLogging(Key); + if (response != eDeviceRegistrationUnRegistrationResponse.Success) + { + //Debug.Console(0, this, "ERROR: Cannot register Crestron device: {0}", response); + return false; + } } IsRegistered.FireUpdate(); @@ -86,7 +89,10 @@ namespace PepperDash.Essentials.Core { AddPostActivationAction(() => { - var response = Hardware.RegisterWithLogging(Key); + if (Hardware.Registerable && !Hardware.Registered) + { + var response = Hardware.RegisterWithLogging(Key); + } IsRegistered.FireUpdate(); }); diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsInternalVirtualDmTxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsInternalVirtualDmTxController.cs index 75ba7e29..c9c2f261 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsInternalVirtualDmTxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsInternalVirtualDmTxController.cs @@ -47,16 +47,23 @@ namespace PepperDash.Essentials.DM { get { - if (InputCard.VideoSourceFeedback != eDmps3InputVideoSource.Auto) - return InputCard.VideoSourceFeedback; - else // auto + try { - if (InputCard.HdmiInputPort.SyncDetectedFeedback.BoolValue) - return eDmps3InputVideoSource.Hdmi; - else if (InputCard.VgaInputPort.SyncDetectedFeedback.BoolValue) - return eDmps3InputVideoSource.Vga; - else - return eDmps3InputVideoSource.Bnc; + if (InputCard.VideoSourceFeedback != eDmps3InputVideoSource.Auto) + return InputCard.VideoSourceFeedback; + else // auto + { + if (InputCard.HdmiInputPort.SyncDetectedFeedback.BoolValue) + return eDmps3InputVideoSource.Hdmi; + else if (InputCard.VgaInputPort.SyncDetectedFeedback.BoolValue) + return eDmps3InputVideoSource.Vga; + else + return eDmps3InputVideoSource.Bnc; + } + } + catch + { + return eDmps3InputVideoSource.Bnc; } } } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index 5c03e8e9..38a0aed9 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -861,6 +861,7 @@ namespace PepperDash.Essentials.DM void Dmps_DMInputChange(Switch device, DMInputEventArgs args) { + Debug.Console(2, this, "DMInputChange Input: {0} EventId: {1}", args.Number, args.EventId.ToString()); try { switch (args.EventId) @@ -871,6 +872,12 @@ namespace PepperDash.Essentials.DM InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); break; } + case (DMInputEventIds.EndpointOnlineEventId): + { + Debug.Console(2, this, "DM Input EndpointOnlineEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); + InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); + break; + } case (DMInputEventIds.VideoDetectedEventId): { Debug.Console(2, this, "DM Input {0} VideoDetectedEventId", args.Number); @@ -916,6 +923,11 @@ namespace PepperDash.Essentials.DM { OutputEndpointOnlineFeedbacks[output].FireUpdate(); } + else if (args.EventId == DMOutputEventIds.EndpointOnlineEventId + && OutputEndpointOnlineFeedbacks.ContainsKey(output)) + { + OutputEndpointOnlineFeedbacks[output].FireUpdate(); + } else if (args.EventId == DMOutputEventIds.VideoOutEventId) { if (outputCard != null && outputCard.VideoOutFeedback != null) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs index 00e3b974..2343f65a 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs @@ -323,7 +323,7 @@ namespace PepperDash.Essentials.DM.Chassis IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); - trilist.StringInput[joinMap.Name.JoinNumber].StringValue = "DM Switcher"; + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = this.Name; for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) { diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs index a9282693..ced21918 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs @@ -30,14 +30,15 @@ namespace PepperDash.Essentials.DM : base(key, name, device) { _rmc = device; + // if wired to a chassis, skip registration step in base class PreventRegistration = _rmc.DMOutput != null; AddToFeedbackList(VideoOutputResolutionFeedback, EdidManufacturerFeedback, EdidSerialNumberFeedback, EdidNameFeedback, EdidPreferredTimingFeedback); - + DeviceInfo = new DeviceInfo(); - _rmc.OnlineStatusChange += (currentDevice, args) => { if (args.DeviceOnLine) UpdateDeviceInfo(); }; + IsOnline.OutputChange += (currentDevice, args) => { if (args.BoolValue) UpdateDeviceInfo(); }; } protected void LinkDmRmcToApi(DmRmcControllerBase rmc, BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) @@ -60,7 +61,7 @@ namespace PepperDash.Essentials.DM Debug.Console(1, rmc, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - rmc.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); trilist.StringInput[joinMap.Name.JoinNumber].StringValue = rmc.Name; if (rmc.VideoOutputResolutionFeedback != null) rmc.VideoOutputResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentOutputResolution.JoinNumber]); @@ -330,53 +331,84 @@ namespace PepperDash.Essentials.DM var parentDev = DeviceManager.GetDeviceForKey(pKey); if (parentDev is DmpsRoutingController) { - if ((parentDev as DmpsRoutingController).Dmps4kType) + var dmps = parentDev as DmpsRoutingController; + //Check that the input is within range of this chassis' possible inputs + var num = props.ParentOutputNumber; + Debug.Console(1, "Creating DMPS device '{0}'. Output number '{1}'.", key, num); + if (num <= 0 || num > dmps.Dmps.SwitcherOutputs.Count) { - return GetDmRmcControllerForDmps4k(key, name, typeName, parentDev as DmpsRoutingController, props.ParentOutputNumber); + Debug.Console(0, "Cannot create DMPS device '{0}'. Output number '{1}' is out of range", + key, num); + return null; } - else + // Must use different constructor for DMPS4K types. No IPID + if (Global.ControlSystemIsDmps4kType) { - return GetDmRmcControllerForDmps(key, name, typeName, ipid, parentDev as DmpsRoutingController, props.ParentOutputNumber); + var rmc = GetDmRmcControllerForDmps4k(key, name, typeName, dmps, props.ParentOutputNumber); + Debug.Console(0, "DM endpoint output {0} is for Dmps4k, changing online feedback to chassis", num); + rmc.IsOnline = dmps.OutputEndpointOnlineFeedbacks[num]; + rmc.IsOnline.OutputChange += (currentDevice, args) => + { + foreach (var feedback in rmc.Feedbacks) + { + if (feedback != null) + feedback.FireUpdate(); + } + }; + return rmc; } + return GetDmRmcControllerForDmps(key, name, typeName, ipid, dmps, props.ParentOutputNumber); } - if (!(parentDev is IDmSwitch)) - { - Debug.Console(0, "Cannot create DM device '{0}'. '{1}' is not a DM Chassis.", - key, pKey); - return null; - } + else if (parentDev is DmChassisController) + { + var controller = parentDev as DmChassisController; + var chassis = controller.Chassis; + var num = props.ParentOutputNumber; + Debug.Console(1, "Creating DM Chassis device '{0}'. Output number '{1}'.", key, num); - var chassis = (parentDev as IDmSwitch).Chassis; - var num = props.ParentOutputNumber; - - if (num <= 0 || num > chassis.NumberOfOutputs) - { - Debug.Console(0, "Cannot create DM device '{0}'. Output number '{1}' is out of range", - key, num); - return null; - } - - var controller = parentDev as IDmSwitch; - controller.RxDictionary.Add(num, key); - // Catch constructor failures, mainly dues to IPID - try - { - // Must use different constructor for CPU3 chassis types. No IPID - if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || - chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || - chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || - chassis is DmMd128x128 || chassis is DmMd64x64) - { - return GetDmRmcControllerForCpu3Chassis(key, name, typeName, chassis, num, parentDev); - } - - return GetDmRmcControllerForCpu2Chassis(key, name, typeName, ipid, chassis, num, parentDev); - } - catch (Exception e) - { - Debug.Console(0, "[{0}] WARNING: Cannot create DM-RMC device: {1}", key, e.Message); - return null; - } + if (num <= 0 || num > chassis.NumberOfOutputs) + { + Debug.Console(0, "Cannot create DM device '{0}'. Output number '{1}' is out of range", + key, num); + return null; + } + controller.RxDictionary.Add(num, key); + // Catch constructor failures, mainly dues to IPID + try + { + // Must use different constructor for CPU3 chassis types. No IPID + if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || + chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || + chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || + chassis is DmMd128x128 || chassis is DmMd64x64) + { + var rmc = GetDmRmcControllerForCpu3Chassis(key, name, typeName, chassis, num, parentDev); + Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); + rmc.IsOnline = controller.OutputEndpointOnlineFeedbacks[num]; + rmc.IsOnline.OutputChange += (currentDevice, args) => + { + foreach (var feedback in rmc.Feedbacks) + { + if (feedback != null) + feedback.FireUpdate(); + } + }; + return rmc; + } + return GetDmRmcControllerForCpu2Chassis(key, name, typeName, ipid, chassis, num, parentDev); + } + catch (Exception e) + { + Debug.Console(0, "[{0}] WARNING: Cannot create DM-RMC device: {1}", key, e.Message); + return null; + } + } + else + { + Debug.Console(0, "Cannot create DM device '{0}'. '{1}' is not a DM Chassis or DMPS.", + key, pKey); + return null; + } } private static CrestronGenericBaseDevice GetDmRmcControllerForCpu2Chassis(string key, string name, string typeName, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs index 5eb2d7b5..4883849e 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs @@ -137,7 +137,7 @@ namespace PepperDash.Essentials.DM try { // Must use different constructor for CPU3 or DMPS3-4K types. No IPID - if (isCpu3 || Global.ControlSystemIsDmps4kType) + if (isCpu3 || (parentDev is DmpsRoutingController && Global.ControlSystemIsDmps4kType)) { if (typeName.StartsWith("dmtx200")) return new DmTx200Controller(key, name, new DmTx200C2G(dmInput)); @@ -145,7 +145,7 @@ namespace PepperDash.Essentials.DM return new DmTx201CController(key, name, new DmTx201C(dmInput)); if (typeName.StartsWith("dmtx201s")) return new DmTx201SController(key, name, new DmTx201S(dmInput)); - if (typeName.StartsWith("dmtx4k100")) + if (typeName.StartsWith("dmtx4k100")) return new DmTx4k100Controller(key, name, new DmTx4K100C1G(dmInput)); if (typeName.StartsWith("dmtx4kz100")) return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(dmInput)); @@ -153,7 +153,7 @@ namespace PepperDash.Essentials.DM return new DmTx4k202CController(key, name, new DmTx4k202C(dmInput)); if (typeName.StartsWith("dmtx4kz202")) return new DmTx4kz202CController(key, name, new DmTx4kz202C(dmInput)); - if (typeName.StartsWith("dmtx4k302")) + if (typeName.StartsWith("dmtx4k302")) return new DmTx4k302CController(key, name, new DmTx4k302C(dmInput)); if (typeName.StartsWith("dmtx4kz302")) return new DmTx4kz302CController(key, name, new DmTx4kz302C(dmInput)); @@ -228,6 +228,41 @@ namespace PepperDash.Essentials.DM } AddToFeedbackList(ActiveVideoInputFeedback); + + var parentDev = DeviceManager.GetDeviceForKey(key); + var num = hardware.DMInput.Number; + + //If Dmps4K, change online feedback to chassis, tx feedback does not work + if (parentDev is DmpsRoutingController && Global.ControlSystemIsDmps4kType) + { + var dmps = parentDev as DmpsRoutingController; + Debug.Console(0, "DM endpoint input {0} is for Dmps4k, changing online feedback to chassis", num); + IsOnline = dmps.InputEndpointOnlineFeedbacks[num]; + } + //If Cpu3 Chassis, change online feedback to chassis, tx feedback does not work + else if (parentDev is DmChassisController) + { + var controller = parentDev as DmChassisController; + var chassis = controller.Chassis; + + if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || + chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || + chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || + chassis is DmMd128x128 || chassis is DmMd64x64) + { + Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); + IsOnline = controller.InputEndpointOnlineFeedbacks[num]; + } + } + + IsOnline.OutputChange += (currentDevice, args) => + { + foreach (var feedback in Feedbacks) + { + if (feedback != null) + feedback.FireUpdate(); + } + }; } protected DmTxControllerBase(string key, string name, DmHDBasedTEndPoint hardware) : base(key, name, hardware) From 6dbdd0587d22431cef4992ddea9c76d4a81ae6bf Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Wed, 15 Jun 2022 08:49:52 -0400 Subject: [PATCH 082/202] Reworks audio routing on DMPS-4K units. --- .../Chassis/DmpsDigitalOutputController.cs | 171 +++++++++ .../Chassis/DmpsMicrophoneController.cs | 3 + .../Chassis/DmpsRoutingController.cs | 344 ++++++++++++++---- .../PepperDash_Essentials_DM.csproj | 1 + 4 files changed, 447 insertions(+), 72 deletions(-) create mode 100644 essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs new file mode 100644 index 00000000..49b5c1c5 --- /dev/null +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro.DM; +using Crestron.SimplSharpPro.DM.Cards; + +using PepperDash.Core; +using PepperDash.Essentials.Core; + + +namespace PepperDash.Essentials.DM +{ + /// + /// + /// + public class DmpsDigitalOutputController : Device, IRoutingNumericWithFeedback, IHasFeedback + { + public Card.Dmps3OutputBase OutputCard { get; protected set; } + + public RoutingInputPort None { get; protected set; } + public RoutingInputPort DigitalMix1 { get; protected set; } + public RoutingInputPort DigitalMix2 { get; protected set; } + public RoutingInputPort AudioFollowsVideo { get; protected set; } + + public RoutingOutputPort DigitalAudioOut { get; protected set; } + + public IntFeedback AudioSourceNumericFeedback { get; protected set; } + + /// + /// Returns a list containing the Outputs that we want to expose. + /// + public FeedbackCollection Feedbacks { get; private set; } + + public virtual RoutingPortCollection InputPorts + { + get + { + return new RoutingPortCollection + { + None, + DigitalMix1, + DigitalMix2, + AudioFollowsVideo + }; + } + } + + public RoutingPortCollection OutputPorts + { + get + { + return new RoutingPortCollection { DigitalAudioOut }; + } + } + + public DmpsDigitalOutputController(string key, string name, Card.Dmps3OutputBase outputCard) + : base(key, name) + { + Feedbacks = new FeedbackCollection(); + OutputCard = outputCard; + + if (outputCard is Card.Dmps3DmOutputBackend) + { + AudioSourceNumericFeedback = new IntFeedback(() => + { + return (int)(outputCard as Card.Dmps3DmOutputBackend).AudioOutSourceDeviceFeedback; + }); + DigitalAudioOut = new RoutingOutputPort(DmPortName.DmOut + OutputCard.Number, eRoutingSignalType.Audio, eRoutingPortConnectionType.DmCat, null, this); + } + + else if (outputCard is Card.Dmps3HdmiOutputBackend) + { + AudioSourceNumericFeedback = new IntFeedback(() => + { + return (int)(outputCard as Card.Dmps3HdmiOutputBackend).AudioOutSourceDeviceFeedback; + }); + DigitalAudioOut = new RoutingOutputPort(DmPortName.HdmiOut + OutputCard.Number, eRoutingSignalType.Audio, eRoutingPortConnectionType.Hdmi, null, this); + } + else + { + return; + } + + None = new RoutingInputPort("None", eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio, + eDmps34KAudioOutSourceDevice.NoRoute, this); + DigitalMix1 = new RoutingInputPort("DigitalMix1", eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio, + eDmps34KAudioOutSourceDevice.DigitalMixer1, this); + DigitalMix2 = new RoutingInputPort("DigitalMix2", eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio, + eDmps34KAudioOutSourceDevice.DigitalMixer2, this); + AudioFollowsVideo = new RoutingInputPort("AudioFollowsVideo", eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio, + eDmps34KAudioOutSourceDevice.AudioFollowsVideo, this); + + AddToFeedbackList(AudioSourceNumericFeedback); + } + + /// + /// Adds feedback(s) to the list + /// + /// + public void AddToFeedbackList(params Feedback[] newFbs) + { + foreach (var f in newFbs) + { + if (f != null) + { + if (!Feedbacks.Contains(f)) + { + Feedbacks.Add(f); + } + } + } + } + + public virtual void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type) + { + Debug.Console(2, this, "Executing Numeric Switch to input {0}.", input); + + switch (input) + { + case 0: + { + ExecuteSwitch(None.Selector, null, type); + break; + } + case 1: + { + ExecuteSwitch(DigitalMix1.Selector, null, type); + break; + } + case 2: + { + ExecuteSwitch(DigitalMix2.Selector, null, type); + break; + } + case 3: + { + ExecuteSwitch(AudioFollowsVideo.Selector, null, type); + break; + } + } + + } + + #region IRouting Members + + public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) + { + if ((signalType | eRoutingSignalType.Audio) == eRoutingSignalType.Audio) + { + if (OutputCard is Card.Dmps3DmOutputBackend) + { + (OutputCard as Card.Dmps3DmOutputBackend).AudioOutSourceDevice = (eDmps34KAudioOutSourceDevice)inputSelector; + } + else if (OutputCard is Card.Dmps3HdmiOutputBackend) + { + (OutputCard as Card.Dmps3HdmiOutputBackend).AudioOutSourceDevice = (eDmps34KAudioOutSourceDevice)inputSelector; + } + } + } + + #endregion + + #region IRoutingFeedback Members + + public event EventHandler NumericSwitchChange; + + #endregion + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsMicrophoneController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsMicrophoneController.cs index 30b2cfab..29dc0693 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsMicrophoneController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsMicrophoneController.cs @@ -38,6 +38,9 @@ namespace PepperDash.Essentials.DM void Dmps_MicrophoneChange(MicrophoneBase mic, GenericEventArgs args) { + if (args.EventId == MicrophoneEventIds.VuFeedBackEventId) + return; + Debug.Console(2, "Dmps Microphone Controller Index: {0} EventId: {1}", mic.ID, args.EventId.ToString()); if(Mics.ContainsKey(mic.ID)) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index 38a0aed9..55c49a96 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -59,6 +59,7 @@ namespace PepperDash.Essentials.DM public Dictionary InputNames { get; set; } public Dictionary OutputNames { get; set; } public Dictionary VolumeControls { get; private set; } + public Dictionary DigitalAudioOutputs { get; private set; } public DmpsMicrophoneController Microphones { get; private set; } public const int RouteOffTime = 500; @@ -155,6 +156,7 @@ namespace PepperDash.Essentials.DM InputPorts = new RoutingPortCollection(); OutputPorts = new RoutingPortCollection(); VolumeControls = new Dictionary(); + DigitalAudioOutputs = new Dictionary(); TxDictionary = new Dictionary(); RxDictionary = new Dictionary(); @@ -246,13 +248,15 @@ namespace PepperDash.Essentials.DM { return; } - foreach (var kvp in OutputNames) { var output = (Dmps.SwitcherOutputs[kvp.Key] as DMOutput); - if (output != null && output.Name.Type != eSigType.NA) + if (output != null) { - output.Name.StringValue = kvp.Value; + if (output.Name.Supported && kvp.Value.Length > 0) + { + output.Name.StringValue = kvp.Value; + } } } } @@ -266,9 +270,12 @@ namespace PepperDash.Essentials.DM foreach (var kvp in InputNames) { var input = (Dmps.SwitcherInputs[kvp.Key] as DMInput); - if (input != null && input.Name.Type != eSigType.NA) + if (input != null) { - input.Name.StringValue = kvp.Value; + if (input.Name.Supported && kvp.Value.Length > 0) + { + input.Name.StringValue = kvp.Value; + } } } } @@ -376,9 +383,20 @@ namespace PepperDash.Essentials.DM } if (OutputNameFeedbacks[ioSlot] != null) { - OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); - OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputVideoNames.JoinNumber + ioSlotJoin]); - OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputAudioNames.JoinNumber + ioSlotJoin]); + if (Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3DmOutput || + Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3DmOutputBackend || + Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3HdmiOutput || + Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3HdmiOutputBackend) + { + OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputVideoNames.JoinNumber + ioSlotJoin]); + OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); + OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputAudioNames.JoinNumber + ioSlotJoin]); + } + else + { + OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); + OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputAudioNames.JoinNumber + ioSlotJoin]); + } } if (OutputVideoRouteNameFeedbacks[ioSlot] != null) { @@ -402,11 +420,15 @@ namespace PepperDash.Essentials.DM { if (Global.ControlSystemIsDmps4kType) { - //DMPS-4K audio inputs 1-5 are aux inputs - for (uint i = 1; i <= 5; i++) + //DMPS-4K audio inputs 1-5 are aux inputs, add them after regular dm cards + for (ushort i = 1; i <= 5; i++) { - trilist.StringInput[joinMap.InputAudioNames.JoinNumber + i - 1].StringValue = String.Format("Aux Input {0}", i); + trilist.StringInput[joinMap.InputAudioNames.JoinNumber + i - 1 + (ushort)Dmps.SwitcherInputs.Count].StringValue = String.Format("Aux Input {0}", i); } + + //Add DMPS-4K mixer input names to end of inputs + trilist.StringInput[joinMap.InputAudioNames.JoinNumber + (uint)Dmps.SwitcherInputs.Count + 5].StringValue = "Digital Mixer 1"; + trilist.StringInput[joinMap.InputAudioNames.JoinNumber + (uint)Dmps.SwitcherInputs.Count + 6].StringValue = "Digital Mixer 2"; } for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++) { @@ -425,16 +447,7 @@ namespace PepperDash.Essentials.DM { InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputVideoNames.JoinNumber + ioSlotJoin]); - - if (Global.ControlSystemIsDmps4kType) - { - //DMPS-4K Audio Inputs are offset by 5 - InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin + 5]); - } - else - { - InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin]); - } + InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin]); } trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s => @@ -496,7 +509,7 @@ namespace PepperDash.Essentials.DM }); AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() => { - try + if (!Global.ControlSystemIsDmps4kType) { if (outputCard.AudioOutFeedback != null) { @@ -504,15 +517,58 @@ namespace PepperDash.Essentials.DM } return 0; } - catch (NotSupportedException) + else { - return (ushort)outputCard.AudioOutSourceFeedback; + + if (outputCard is Card.Dmps3DmOutputBackend || outputCard is Card.Dmps3HdmiOutputBackend) + { + //Special cases for DMPS-4K digital audio output + if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 0) + return 0; + else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 1) + return (ushort)Dmps.SwitcherInputs.Count + 6; + else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 2) + return (ushort)Dmps.SwitcherInputs.Count + 7; + else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 3) + return (ushort)outputCard.VideoOutFeedback.Number; + else + return 0; + } + else if (outputCard.AudioOutSourceFeedback == eDmps34KAudioOutSource.NoRoute) + { + //Fixes for weird audio indexing on DMPS3-4K + return 0; + } + else if (outputCard.AudioOutSourceFeedback == eDmps34KAudioOutSource.AirMedia8) + { + //Fixes for weird audio indexing on DMPS3-4K + return 8; + } + else if (outputCard.AudioOutSourceFeedback == eDmps34KAudioOutSource.AirMedia9) + { + //Fixes for weird audio indexing on DMPS3-4K + return 9; + } + else if ((ushort)outputCard.AudioOutSourceFeedback <= 5) + { + //Move analog inputs to after regular dm cards + return (ushort)outputCard.AudioOutSourceFeedback + (ushort)Dmps.SwitcherInputs.Count; + } + else + { + //Fixes for weird audio indexing on DMPS3-4K + return (ushort)outputCard.AudioOutSourceFeedback - 5; + } } }); OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() => { - if (outputCard.NameFeedback != null && outputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue)) + if(OutputNames.ContainsKey(outputCard.Number)) + { + return OutputNames[outputCard.Number]; + } + else if (outputCard.NameFeedback != null && outputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue)) { Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue); return outputCard.NameFeedback.StringValue; @@ -530,9 +586,33 @@ namespace PepperDash.Essentials.DM }); OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => { - if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null) + if (!Global.ControlSystemIsDmps4kType) { - return outputCard.AudioOutFeedback.NameFeedback.StringValue; + if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null) + { + return outputCard.AudioOutFeedback.NameFeedback.StringValue; + } + } + else + { + if (outputCard is Card.Dmps3DmOutputBackend || outputCard is Card.Dmps3HdmiOutputBackend) + { + //Special cases for DMPS-4K digital audio output + if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 0) + return NoRouteText; + else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 1) + return "Digital Mix 1"; + else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 2) + return "Digital Mix 2"; + else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 3) + return outputCard.VideoOutFeedback.NameFeedback.StringValue; + else + return NoRouteText; + } + else + { + return outputCard.AudioOutSourceFeedback.ToString(); + } } return NoRouteText; }); @@ -570,13 +650,15 @@ namespace PepperDash.Essentials.DM InputNameFeedbacks[inputCard.Number] = new StringFeedback(() => { - if (inputCard.NameFeedback != null && inputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(inputCard.NameFeedback.StringValue)) + if (InputNames.ContainsKey(inputCard.Number)) + { + return InputNames[inputCard.Number]; + } + else if (inputCard.NameFeedback != null && inputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(inputCard.NameFeedback.StringValue)) { Debug.Console(2, this, "Input Card {0} Name: {1}", inputCard.Number, inputCard.NameFeedback.StringValue); return inputCard.NameFeedback.StringValue; } - - Debug.Console(2, this, "Input Card {0} Name is null", inputCard.Number); return ""; }); @@ -705,10 +787,11 @@ namespace PepperDash.Essentials.DM else if (outputCard is Card.Dmps3HdmiOutputBackend) { var hdmiOutputCard = outputCard as Card.Dmps3HdmiOutputBackend; - var cecPort = hdmiOutputCard.HdmiOutputPort; - AddHdmiOutputPort(number, cecPort); + var audioOutput = new DmpsDigitalOutputController(string.Format("processor-avRouting-HdmiAudioOut{0}", number), string.Format("Hdmi Audio Output {0} Router", number), hdmiOutputCard); + DigitalAudioOutputs.Add(number, audioOutput); + DeviceManager.AddDevice(audioOutput); } else if (outputCard is Card.Dmps3DmOutput) { @@ -720,6 +803,9 @@ namespace PepperDash.Essentials.DM else if (outputCard is Card.Dmps3DmOutputBackend) { AddDmOutputPort(number); + var audioOutput = new DmpsDigitalOutputController(string.Format("processor-avRouting-DmAudioOut{0}", number), string.Format("Dm Audio Output {0} Router", number), outputCard as Card.Dmps3DmOutputBackend); + DigitalAudioOutputs.Add(number, audioOutput); + DeviceManager.AddDevice(audioOutput); } else if (outputCard is Card.Dmps3ProgramOutput) { @@ -737,7 +823,7 @@ namespace PepperDash.Essentials.DM { AddAudioOnlyOutputPort(number, "Aux1"); - var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux1Output); + var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Aux1 Audio Output", outputCard as Card.Dmps3Aux1Output); DeviceManager.AddDevice(aux1Output); } @@ -746,7 +832,7 @@ namespace PepperDash.Essentials.DM { AddAudioOnlyOutputPort(number, "Aux2"); - var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux2Output); + var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Aux2 Audio Output", outputCard as Card.Dmps3Aux2Output); DeviceManager.AddDevice(aux2Output); } @@ -788,7 +874,7 @@ namespace PepperDash.Essentials.DM || number == (uint)CrestronControlSystem.eDmps34K350COutputs.Mix2) AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps34K250COutputs.Mix2.ToString()); - var audioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number % 2 + 1), string.Format("Digital Audio Output {0}", number % 2 + 1), outputCard as Card.Dmps3DigitalMixOutput); + var audioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number % 2 + 1), string.Format("Digital Audio Mix {0}", number % 2 + 1), outputCard as Card.Dmps3DigitalMixOutput); DeviceManager.AddDevice(audioOutput); } else @@ -902,14 +988,13 @@ namespace PepperDash.Essentials.DM } void Dmps_DMOutputChange(Switch device, DMOutputEventArgs args) { - Debug.Console(2, this, "DMOutputChange Output: {0} EventId: {1}", args.Number, args.EventId.ToString()); - if (args.EventId == DMOutputEventIds.OutputVuFeedBackEventId) { //Frequently called event that isn't needed return; } + Debug.Console(2, this, "DMOutputChange Output: {0} EventId: {1}", args.Number, args.EventId.ToString()); var output = args.Number; DMOutput outputCard = Dmps.SwitcherOutputs[output] as DMOutput; @@ -942,41 +1027,68 @@ namespace PepperDash.Essentials.DM { OutputVideoRouteNameFeedbacks[output].FireUpdate(); } + if (outputCard is Card.Dmps3DmOutputBackend || outputCard is Card.Dmps3HdmiOutputBackend) + { + if (AudioOutputFeedbacks.ContainsKey(output)) + { + AudioOutputFeedbacks[output].FireUpdate(); + } + if (OutputAudioRouteNameFeedbacks.ContainsKey(output)) + { + OutputAudioRouteNameFeedbacks[output].FireUpdate(); + } + } } else if (args.EventId == DMOutputEventIds.AudioOutEventId) { - try + if (!Global.ControlSystemIsDmps4kType) { if (outputCard != null && outputCard.AudioOutFeedback != null) { Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, outputCard.AudioOutFeedback.Number, output); } - if (AudioOutputFeedbacks.ContainsKey(output)) - { - AudioOutputFeedbacks[output].FireUpdate(); - } } - catch (NotSupportedException) + else { if (outputCard != null) { - Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", Name, - outputCard.AudioOutSourceFeedback, output); - } - if (AudioOutputFeedbacks.ContainsKey(output)) - { - AudioOutputFeedbacks[output].FireUpdate(); + if (outputCard is Card.Dmps3DmOutputBackend || outputCard is Card.Dmps3HdmiOutputBackend) + { + DigitalAudioOutputs[output].AudioSourceNumericFeedback.FireUpdate(); + } + else + { + Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", Name, + outputCard.AudioOutSourceFeedback, output); + } } } + if (AudioOutputFeedbacks.ContainsKey(output)) + { + AudioOutputFeedbacks[output].FireUpdate(); + } + if (OutputAudioRouteNameFeedbacks.ContainsKey(output)) + { + OutputAudioRouteNameFeedbacks[output].FireUpdate(); + } } else if (args.EventId == DMOutputEventIds.OutputNameEventId && OutputNameFeedbacks.ContainsKey(output)) { - Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output); OutputNameFeedbacks[output].FireUpdate(); } - + else if (args.EventId == DMOutputEventIds.DigitalMixerAudioSourceFeedBackEventId) + { + if (AudioOutputFeedbacks.ContainsKey(output)) + { + AudioOutputFeedbacks[output].FireUpdate(); + } + if (OutputAudioRouteNameFeedbacks.ContainsKey(output)) + { + OutputAudioRouteNameFeedbacks[output].FireUpdate(); + } + } } void Dmps_DMSystemChange(Switch device, DMSystemEventArgs args) @@ -1024,9 +1136,6 @@ namespace PepperDash.Essentials.DM Debug.Console(2, this, "Attempting a DM route from input {0} to output {1} {2}", inputSelector, outputSelector, sigType); - //var input = Convert.ToUInt32(inputSelector); // Cast can sometimes fail - //var output = Convert.ToUInt32(outputSelector); - var input = inputSelector as DMInput; var output = outputSelector as DMOutput; @@ -1044,7 +1153,7 @@ namespace PepperDash.Essentials.DM if (input == null || (input.Number <= Dmps.NumberOfSwitcherInputs && output.Number <= Dmps.NumberOfSwitcherOutputs && sigTypeIsUsbOrVideo) || - (input.Number <= Dmps.NumberOfSwitcherInputs + 5 && output.Number <= Dmps.NumberOfSwitcherOutputs && + (input.Number <= (Dmps.NumberOfSwitcherInputs) && output.Number <= Dmps.NumberOfSwitcherOutputs && (sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio)) { // Check to see if there's an off timer waiting on this and if so, cancel @@ -1063,11 +1172,6 @@ namespace PepperDash.Essentials.DM } } - - //DMOutput dmOutputCard = output == 0 ? null : Dmps.SwitcherOutputs[output] as DMOutput; - - //if (inCard != null) - //{ // NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) { @@ -1076,19 +1180,34 @@ namespace PepperDash.Essentials.DM if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) { - try + if(!Global.ControlSystemIsDmps4kType) { output.AudioOut = input; } - catch (NotSupportedException) + else { - Debug.Console(1, this, "Routing input {0} audio to output {1}", - (eDmps34KAudioOutSource) (input == null ? 0 : input.Number), - (CrestronControlSystem.eDmps34K350COutputs) output.Number); - - output.AudioOutSource = input == null - ? eDmps34KAudioOutSource.NoRoute - : (eDmps34KAudioOutSource)input.Number; + if (input == null) + { + output.AudioOutSource = eDmps34KAudioOutSource.NoRoute; + } + else if (input.CardInputOutputType == eCardInputOutputType.Dmps3AirMediaInput || input.CardInputOutputType == eCardInputOutputType.Dmps3AirMediaNoStreamingInput) + { + //Special case for weird AirMedia indexing + if (Dmps.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl) + output.AudioOutSource = eDmps34KAudioOutSource.AirMedia8; + else if (Dmps.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) + output.AudioOutSource = eDmps34KAudioOutSource.AirMedia9; + } + else if (input.Number <= Dmps.SwitcherInputs.Count) + { + //Shift video inputs by 5 for weird DMPS3-4K indexing + output.AudioOutSource = (eDmps34KAudioOutSource)(input.Number + 5); + } + else + { + //Shift analog inputs back to inputs 1-5 + output.AudioOutSource = (eDmps34KAudioOutSource)(input.Number - Dmps.SwitcherInputs.Count); + } } } @@ -1122,10 +1241,91 @@ namespace PepperDash.Essentials.DM public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType sigType) { - var input = inputSelector == 0 ? null : Dmps.SwitcherInputs[inputSelector]; - var output = Dmps.SwitcherOutputs[outputSelector]; + if (EnableRouting == false) + { + return; + } - ExecuteSwitch(input, output, sigType); + Debug.Console(1, this, "Attempting a numeric switch from input {0} to output {1} {2}", inputSelector, outputSelector, sigType); + + if((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) + { + if (inputSelector <= Dmps.SwitcherInputs.Count && outputSelector <= Dmps.SwitcherOutputs.Count) + { + var input = inputSelector == 0 ? null : Dmps.SwitcherInputs[inputSelector]; + var output = Dmps.SwitcherOutputs[outputSelector]; + + ExecuteSwitch(input, output, sigType); + } + } + else if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) + { + //Special case for DMPS-4K digital audio output + if (Global.ControlSystemIsDmps4kType) + { + if (DigitalAudioOutputs.ContainsKey(outputSelector)) + { + if (inputSelector == 0) //Clear action + { + DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(0, 0, eRoutingSignalType.Audio); + } + else if (inputSelector <= Dmps.SwitcherInputs.Count) //DMPS-4K video inputs, set to audio follows video + { + DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(3, 0, eRoutingSignalType.Audio); + //Force video route since it is now set so audio follows video + ExecuteNumericSwitch(inputSelector, outputSelector, eRoutingSignalType.Video); + } + else if (inputSelector == Dmps.SwitcherInputs.Count + 6) + { + //Set to mix 1 + DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(1, 0, eRoutingSignalType.Audio); + } + else if (inputSelector == Dmps.SwitcherInputs.Count + 7) + { + //Set to mix 2 + DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(2, 0, eRoutingSignalType.Audio); + } + } + else if (inputSelector <= (Dmps.SwitcherInputs.Count + 5) && outputSelector <= Dmps.SwitcherOutputs.Count) + { + var output = Dmps.SwitcherOutputs[outputSelector] as DMOutput; + if (inputSelector == 0) + { + output.AudioOutSource = eDmps34KAudioOutSource.NoRoute; + } + else if(inputSelector > Dmps.SwitcherInputs.Count) + { + //Shift analog inputs back to inputs 1-5 + Debug.Console(1, this, "Attempting analog route input {0} to output {1}", inputSelector - Dmps.SwitcherInputs.Count, outputSelector); + output.AudioOutSource = (eDmps34KAudioOutSource)(inputSelector - Dmps.SwitcherInputs.Count); + } + else if (inputSelector <= Dmps.SwitcherInputs.Count) + { + var input = Dmps.SwitcherInputs[inputSelector] as DMInput; + if (input.CardInputOutputType == eCardInputOutputType.Dmps3AirMediaInput || input.CardInputOutputType == eCardInputOutputType.Dmps3AirMediaNoStreamingInput) + { + //Special case for weird AirMedia indexing + if (Dmps.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl) + output.AudioOutSource = eDmps34KAudioOutSource.AirMedia8; + else if (Dmps.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) + output.AudioOutSource = eDmps34KAudioOutSource.AirMedia9; + } + else + { + //Shift video inputs by 5 for weird DMPS3-4K indexing + output.AudioOutSource = (eDmps34KAudioOutSource)(inputSelector + 5); + } + } + } + } + + else if (inputSelector <= Dmps.SwitcherInputs.Count && outputSelector <= Dmps.SwitcherOutputs.Count) + { + var output = Dmps.SwitcherOutputs[outputSelector] as DMOutput; + var input = Dmps.SwitcherInputs[inputSelector] as DMInput; + output.AudioOut = input; + } + } } #endregion diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj index ea3dbd5d..41b07237 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -93,6 +93,7 @@ + From 5b94d89bc36df25563599615a6b6b3e5bd0ff53c Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Wed, 15 Jun 2022 20:26:32 -0400 Subject: [PATCH 083/202] Improvements for DMPS3-4K-150 types --- .../PepperDashEssentialsBase/Global/Global.cs | 44 ++- .../Chassis/DmpsAudioOutputController.cs | 333 +++++++++++++----- .../Chassis/DmpsDigitalOutputController.cs | 8 +- .../Chassis/DmpsRoutingController.cs | 105 ++++-- 4 files changed, 356 insertions(+), 134 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs index 9d792437..2bafc2ae 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharp.CrestronDataStore; using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DM; using PepperDash.Core; using PepperDash.Essentials.License; @@ -39,7 +40,14 @@ namespace PepperDash.Essentials.Core { get { - return ControlSystem.ControllerPrompt.ToLower().IndexOf("dmps") > -1; + if(ControlSystem.SystemControl != null) + { + if(ControlSystem.SystemControl.SystemControlType > 0) + { + return true; + } + } + return false; } } @@ -50,7 +58,39 @@ namespace PepperDash.Essentials.Core { get { - return ControlSystemIsDmpsType && ControlSystem.ControllerPrompt.ToLower().IndexOf("4k") > -1; + if(ControlSystem.SystemControl != null) + { + if(ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K150CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K200CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K300CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) + { + return true; + } + } + return false; + } + } + + /// + /// True when the processor type is a DMPS 4K 200/300/250/350 variant + /// + public static bool ControlSystemIsDmps4k3xxType + { + get + { + if(ControlSystem.SystemControl != null) + { + if(ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K200CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K300CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) + { + return true; + } + } + return false; } } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs index 60943270..c3ed2354 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs @@ -17,60 +17,89 @@ using PepperDash.Essentials.DM.Config; namespace PepperDash.Essentials.DM { /// - /// Exposes the volume levels for Program, Aux1 or Aux2 outputs on a DMPS3 chassis + /// Exposes the volume levels for Program, Aux1, Aux2, Codec1, Codec2, and Digital outputs on a DMPS3 chassis /// public class DmpsAudioOutputController : EssentialsBridgeableDevice { - Card.Dmps3OutputBase OutputCard; - public DmpsAudioOutput MasterVolumeLevel { get; private set; } public DmpsAudioOutput SourceVolumeLevel { get; private set; } public DmpsAudioOutput MicsMasterVolumeLevel { get; private set; } public DmpsAudioOutput Codec1VolumeLevel { get; private set; } public DmpsAudioOutput Codec2VolumeLevel { get; private set; } + public DmpsAudioOutputController(string key, string name, DMOutput card, Card.Dmps3DmHdmiAudioOutput.Dmps3AudioOutputStream stream) + : base(key, name) + { + card.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange); + var output = new Dmps3AudioOutputWithMixerBase(stream); + MasterVolumeLevel = new DmpsAudioOutputWithMixer(output, eDmpsLevelType.Master); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + } + public DmpsAudioOutputController(string key, string name, DMOutput card, Card.Dmps3DmHdmiAudioOutput.Dmps3DmHdmiOutputStream stream) + : base(key, name) + { + card.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange); + var output = new Dmps3AudioOutputWithMixerBase(stream); + MasterVolumeLevel = new DmpsAudioOutputWithMixer(output, eDmpsLevelType.Master); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + } + public DmpsAudioOutputController(string key, string name, Card.Dmps3OutputBase card) : base(key, name) { - OutputCard = card; - OutputCard.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange); - - SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source); - MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster); + card.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange); if (card is Card.Dmps3ProgramOutput) { - var output = card as Card.Dmps3ProgramOutput; - MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(card, eDmpsLevelType.Master, output.OutputMixer, output.OutputEqualizer); - Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1); - Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2); + var programOutput = card as Card.Dmps3ProgramOutput; + var output = new Dmps3AudioOutputWithMixerBase(card, programOutput.OutputMixer); + MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(output, eDmpsLevelType.Master, programOutput.OutputEqualizer); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.MicsMaster); + Codec1VolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Codec1); + Codec2VolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Codec2); } else if (card is Card.Dmps3Aux1Output) { - var output = card as Card.Dmps3Aux1Output; - MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(card, eDmpsLevelType.Master, output.OutputMixer, output.OutputEqualizer); - Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2); + var auxOutput = card as Card.Dmps3Aux1Output; + var output = new Dmps3AudioOutputWithMixerBase(card, auxOutput.OutputMixer); + MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(output, eDmpsLevelType.Master, auxOutput.OutputEqualizer); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.MicsMaster); + Codec2VolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Codec2); } else if (card is Card.Dmps3Aux2Output) { - var output = card as Card.Dmps3Aux2Output; - MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(card, eDmpsLevelType.Master, output.OutputMixer, output.OutputEqualizer); - Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1); + var auxOutput = card as Card.Dmps3Aux2Output; + var output = new Dmps3AudioOutputWithMixerBase(card, auxOutput.OutputMixer); + MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(output, eDmpsLevelType.Master, auxOutput.OutputEqualizer); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.MicsMaster); + Codec1VolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Codec1); } else if (card is Card.Dmps3DigitalMixOutput) { - var output = card as Card.Dmps3DigitalMixOutput; - MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, output.OutputMixer); + var mixOutput = card as Card.Dmps3DigitalMixOutput; + var output = new Dmps3AudioOutputWithMixerBase(card, mixOutput.OutputMixer); + MasterVolumeLevel = new DmpsAudioOutputWithMixer(output, eDmpsLevelType.Master); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.MicsMaster); } else if (card is Card.Dmps3HdmiOutput) { - var output = card as Card.Dmps3HdmiOutput; - MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, output.OutputMixer); + var hdmiOutput = card as Card.Dmps3HdmiOutput; + var output = new Dmps3AudioOutputWithMixerBase(card, hdmiOutput.OutputMixer); + MasterVolumeLevel = new DmpsAudioOutputWithMixer(output, eDmpsLevelType.Master); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.MicsMaster); } else if (card is Card.Dmps3DmOutput) { - var output = card as Card.Dmps3DmOutput; - MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, output.OutputMixer); + var dmOutput = card as Card.Dmps3DmOutput; + var output = new Dmps3AudioOutputWithMixerBase(card, dmOutput.OutputMixer); + MasterVolumeLevel = new DmpsAudioOutputWithMixer(output, eDmpsLevelType.Master); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.MicsMaster); } } @@ -250,8 +279,8 @@ namespace PepperDash.Essentials.DM public class DmpsAudioOutputWithMixerAndEq : DmpsAudioOutputWithMixer { private CrestronControlSystem.Dmps3OutputEqualizer Eq; - public DmpsAudioOutputWithMixerAndEq(Card.Dmps3OutputBase output, eDmpsLevelType type, CrestronControlSystem.Dmps3OutputMixer mixer, CrestronControlSystem.Dmps3OutputEqualizer eq) - : base(output, type, mixer) + public DmpsAudioOutputWithMixerAndEq(Dmps3AudioOutputWithMixerBase output, eDmpsLevelType type, CrestronControlSystem.Dmps3OutputEqualizer eq) + : base(output, type) { Eq = eq; } @@ -265,19 +294,19 @@ namespace PepperDash.Essentials.DM public class DmpsAudioOutputWithMixer : DmpsAudioOutput { - IDmps3OutputMixer Mixer; + Dmps3AudioOutputWithMixerBase Output; - public DmpsAudioOutputWithMixer(Card.Dmps3OutputBase output, eDmpsLevelType type, IDmps3OutputMixer mixer) + public DmpsAudioOutputWithMixer(Dmps3AudioOutputWithMixerBase output, eDmpsLevelType type) : base(output, type) { - Mixer = mixer; + Output = output; GetVolumeMax(); GetVolumeMin(); } public void GetVolumeMin() { - MinLevel = (short)Mixer.MinVolumeFeedback.UShortValue; + MinLevel = (short)Output.MinVolumeFeedback.UShortValue; if (VolumeLevelScaledFeedback != null) { VolumeLevelScaledFeedback.FireUpdate(); @@ -286,7 +315,7 @@ namespace PepperDash.Essentials.DM public void GetVolumeMax() { - MaxLevel = (short)Mixer.MaxVolumeFeedback.UShortValue; + MaxLevel = (short)Output.MaxVolumeFeedback.UShortValue; if (VolumeLevelScaledFeedback != null) { VolumeLevelScaledFeedback.FireUpdate(); @@ -295,32 +324,22 @@ namespace PepperDash.Essentials.DM public void RecallPreset(ushort preset) { - if (Mixer is CrestronControlSystem.Dmps3OutputMixer) - { - var presetMixer = Mixer as CrestronControlSystem.Dmps3OutputMixer; - Debug.Console(1, "DMPS Recalling Preset {0}", preset); - presetMixer.PresetNumber.UShortValue = preset; - presetMixer.RecallPreset(); + Output.PresetNumber.UShortValue = preset; + Output.RecallPreset(); + if (!Global.ControlSystemIsDmps4kType) + { //Recall startup volume for main volume level as DMPS3(non-4K) presets don't affect the main volume RecallStartupVolume(); } - else if (Mixer is CrestronControlSystem.Dmps3AttachableOutputMixer) - { - var presetMixer = Mixer as CrestronControlSystem.Dmps3AttachableOutputMixer; - Debug.Console(1, "DMPS Recalling Preset {0}", preset); - presetMixer.PresetNumber.UShortValue = preset; - presetMixer.RecallPreset(); - } - } public void RecallStartupVolume() { - ushort startupVol = Mixer.StartupVolumeFeedback.UShortValue; + ushort startupVol = Output.StartupVolumeFeedback.UShortValue; //Reset startup vol due to bug on DMPS3 where getting the value from above method clears the startup volume - Mixer.StartupVolume.UShortValue = startupVol; - Debug.Console(1, "DMPS Recalling {0} Startup Volume {1}", Output.Name, startupVol); + Output.StartupVolume.UShortValue = startupVol; + Debug.Console(1, "DMPS Recalling Startup Volume {0}", startupVol); SetVolume(startupVol); MuteOff(); } @@ -329,7 +348,6 @@ namespace PepperDash.Essentials.DM public class DmpsAudioOutput : IBasicVolumeWithFeedback { private UShortInputSig Level; - protected Card.Dmps3OutputBase Output; private bool EnableVolumeSend; private ushort VolumeLevelInput; protected short MinLevel { get; set; } @@ -345,9 +363,8 @@ namespace PepperDash.Essentials.DM Action VolumeUpAction; Action VolumeDownAction; - public DmpsAudioOutput(Card.Dmps3OutputBase output, eDmpsLevelType type) + public DmpsAudioOutput(Dmps3AudioOutputBase output, eDmpsLevelType type) { - Output = output; VolumeLevelInput = 0; EnableVolumeSend = false; Type = type; @@ -359,47 +376,46 @@ namespace PepperDash.Essentials.DM case eDmpsLevelType.Master: { Level = output.MasterVolume; - - MuteFeedback = new BoolFeedback(new Func(() => Output.MasterMuteOnFeedBack.BoolValue)); - VolumeLevelFeedback = new IntFeedback(new Func(() => Output.MasterVolumeFeedBack.UShortValue)); - MuteOnAction = new Action(Output.MasterMuteOn); - MuteOffAction = new Action(Output.MasterMuteOff); - VolumeUpAction = new Action((b) => Output.MasterVolumeUp.BoolValue = b); - VolumeDownAction = new Action((b) => Output.MasterVolumeDown.BoolValue = b); + MuteFeedback = new BoolFeedback(new Func(() => output.MasterMuteOnFeedBack.BoolValue)); + VolumeLevelFeedback = new IntFeedback(new Func(() => output.MasterVolumeFeedBack.UShortValue)); + MuteOnAction = new Action(output.MasterMuteOn); + MuteOffAction = new Action(output.MasterMuteOff); + VolumeUpAction = new Action((b) => output.MasterVolumeUp.BoolValue = b); + VolumeDownAction = new Action((b) => output.MasterVolumeDown.BoolValue = b); break; } case eDmpsLevelType.MicsMaster: { - Level = output.MicMasterLevel; - - MuteFeedback = new BoolFeedback(new Func(() => Output.MicMasterMuteOnFeedBack.BoolValue)); - VolumeLevelFeedback = new IntFeedback(new Func(() => Output.MicMasterLevelFeedBack.UShortValue)); - MuteOnAction = new Action(Output.MicMasterMuteOn); - MuteOffAction = new Action(Output.MicMasterMuteOff); - VolumeUpAction = new Action((b) => Output.MicMasterLevelUp.BoolValue = b); - VolumeDownAction = new Action((b) => Output.MicMasterLevelDown.BoolValue = b); + if (output.Card is Card.Dmps3OutputBase) + { + var micOutput = output.Card as Card.Dmps3OutputBase; + Level = micOutput.MicMasterLevel; + MuteFeedback = new BoolFeedback(new Func(() => micOutput.MicMasterMuteOnFeedBack.BoolValue)); + VolumeLevelFeedback = new IntFeedback(new Func(() => micOutput.MicMasterLevelFeedBack.UShortValue)); + MuteOnAction = new Action(micOutput.MicMasterMuteOn); + MuteOffAction = new Action(micOutput.MicMasterMuteOff); + VolumeUpAction = new Action((b) => micOutput.MicMasterLevelUp.BoolValue = b); + VolumeDownAction = new Action((b) => micOutput.MicMasterLevelDown.BoolValue = b); + } break; } case eDmpsLevelType.Source: { Level = output.SourceLevel; - - MuteFeedback = new BoolFeedback(new Func(() => Output.SourceMuteOnFeedBack.BoolValue)); - VolumeLevelFeedback = new IntFeedback(new Func(() => Output.SourceLevelFeedBack.UShortValue)); - MuteOnAction = new Action(Output.SourceMuteOn); - MuteOffAction = new Action(Output.SourceMuteOff); - VolumeUpAction = new Action((b) => Output.SourceLevelUp.BoolValue = b); - VolumeDownAction = new Action((b) => Output.SourceLevelDown.BoolValue = b); + MuteFeedback = new BoolFeedback(new Func(() => output.SourceMuteOnFeedBack.BoolValue)); + VolumeLevelFeedback = new IntFeedback(new Func(() => output.SourceLevelFeedBack.UShortValue)); + MuteOnAction = new Action(output.SourceMuteOn); + MuteOffAction = new Action(output.SourceMuteOff); + VolumeUpAction = new Action((b) => output.SourceLevelUp.BoolValue = b); + VolumeDownAction = new Action((b) => output.SourceLevelDown.BoolValue = b); break; } case eDmpsLevelType.Codec1: { - var programOutput = output as Card.Dmps3ProgramOutput; - - if (programOutput != null) + if (output.Card is Card.Dmps3ProgramOutput) { + var programOutput = output.Card as Card.Dmps3ProgramOutput; Level = programOutput.Codec1Level; - MuteFeedback = new BoolFeedback(new Func(() => programOutput.CodecMute1OnFeedback.BoolValue)); VolumeLevelFeedback = new IntFeedback(new Func(() => programOutput.Codec1LevelFeedback.UShortValue)); MuteOnAction = new Action(programOutput.Codec1MuteOn); @@ -407,12 +423,10 @@ namespace PepperDash.Essentials.DM VolumeUpAction = new Action((b) => programOutput.Codec1LevelUp.BoolValue = b); VolumeDownAction = new Action((b) => programOutput.Codec1LevelDown.BoolValue = b); } - else + else if (output.Card is Card.Dmps3Aux2Output) { - var auxOutput = output as Card.Dmps3Aux2Output; - + var auxOutput = output.Card as Card.Dmps3Aux2Output; Level = auxOutput.Codec1Level; - MuteFeedback = new BoolFeedback(new Func(() => auxOutput.CodecMute1OnFeedback.BoolValue)); VolumeLevelFeedback = new IntFeedback(new Func(() => auxOutput.Codec1LevelFeedback.UShortValue)); MuteOnAction = new Action(auxOutput.Codec1MuteOn); @@ -424,12 +438,10 @@ namespace PepperDash.Essentials.DM } case eDmpsLevelType.Codec2: { - var programOutput = output as Card.Dmps3ProgramOutput; - - if (programOutput != null) + if (output.Card is Card.Dmps3ProgramOutput) { + var programOutput = output.Card as Card.Dmps3ProgramOutput; Level = programOutput.Codec2Level; - MuteFeedback = new BoolFeedback(new Func(() => programOutput.CodecMute1OnFeedback.BoolValue)); VolumeLevelFeedback = new IntFeedback(new Func(() => programOutput.Codec2LevelFeedback.UShortValue)); MuteOnAction = new Action(programOutput.Codec2MuteOn); @@ -437,12 +449,11 @@ namespace PepperDash.Essentials.DM VolumeUpAction = new Action((b) => programOutput.Codec2LevelUp.BoolValue = b); VolumeDownAction = new Action((b) => programOutput.Codec2LevelDown.BoolValue = b); } - else + else if (output.Card is Card.Dmps3Aux1Output) { - var auxOutput = output as Card.Dmps3Aux1Output; + var auxOutput = output.Card as Card.Dmps3Aux1Output; Level = auxOutput.Codec2Level; - MuteFeedback = new BoolFeedback(new Func(() => auxOutput.CodecMute2OnFeedback.BoolValue)); VolumeLevelFeedback = new IntFeedback(new Func(() => auxOutput.Codec2LevelFeedback.UShortValue)); MuteOnAction = new Action(auxOutput.Codec2MuteOn); @@ -463,7 +474,6 @@ namespace PepperDash.Essentials.DM public void SetVolumeScaled(ushort level) { - Debug.Console(2, Debug.ErrorLogLevel.None, "Scaling DMPS volume:{0} level:{1} min:{2} max:{3}", Output.Name, level.ToString(), MinLevel.ToString(), MaxLevel.ToString()); if (ushort.MaxValue + MinLevel != 0) { VolumeLevelInput = (ushort)(level * (MaxLevel - MinLevel) / ushort.MaxValue + MinLevel); @@ -477,7 +487,6 @@ namespace PepperDash.Essentials.DM public ushort ScaleVolumeFeedback(ushort level) { short signedLevel = (short)level; - Debug.Console(2, Debug.ErrorLogLevel.None, "Scaling DMPS volume:{0} feedback:{1} min:{2} max:{3}", Output.Name, signedLevel.ToString(), MinLevel.ToString(), MaxLevel.ToString()); if (MaxLevel - MinLevel != 0) { @@ -538,6 +547,150 @@ namespace PepperDash.Essentials.DM #endregion } + public class Dmps3AudioOutputWithMixerBase : Dmps3AudioOutputBase + { + public UShortOutputSig MinVolumeFeedback { get; private set; } + public UShortOutputSig MaxVolumeFeedback { get; private set; } + public UShortInputSig StartupVolume { get; private set; } + public UShortOutputSig StartupVolumeFeedback { get; private set; } + public UShortInputSig PresetNumber { get; private set; } + + public Action RecallPreset { get; private set; } + + public Dmps3AudioOutputWithMixerBase(Card.Dmps3OutputBase card, CrestronControlSystem.Dmps3OutputMixer mixer) + : base(card) + { + MinVolumeFeedback = mixer.MinVolumeFeedback; + MaxVolumeFeedback = mixer.MaxVolumeFeedback; + StartupVolume = mixer.StartupVolume; + StartupVolumeFeedback = mixer.StartupVolumeFeedback; + PresetNumber = mixer.PresetNumber; + + RecallPreset = new Action(mixer.RecallPreset); + } + + public Dmps3AudioOutputWithMixerBase(Card.Dmps3OutputBase card, CrestronControlSystem.Dmps3AttachableOutputMixer mixer) + : base(card) + { + MinVolumeFeedback = mixer.MinVolumeFeedback; + MaxVolumeFeedback = mixer.MaxVolumeFeedback; + StartupVolume = mixer.StartupVolume; + StartupVolumeFeedback = mixer.StartupVolumeFeedback; + PresetNumber = mixer.PresetNumber; + + RecallPreset = new Action(mixer.RecallPreset); + } + + public Dmps3AudioOutputWithMixerBase(Card.Dmps3DmHdmiAudioOutput.Dmps3AudioOutputStream stream) + : base(stream) + { + var mixer = stream.OutputMixer; + MinVolumeFeedback = mixer.MinVolumeFeedback; + MaxVolumeFeedback = mixer.MaxVolumeFeedback; + StartupVolume = mixer.StartupVolume; + StartupVolumeFeedback = mixer.StartupVolumeFeedback; + PresetNumber = stream.PresetNumber; + RecallPreset = new Action(stream.RecallPreset); + } + + public Dmps3AudioOutputWithMixerBase(Card.Dmps3DmHdmiAudioOutput.Dmps3DmHdmiOutputStream stream) + : base(stream) + { + var mixer = stream.OutputMixer; + MinVolumeFeedback = mixer.MinVolumeFeedback; + MaxVolumeFeedback = mixer.MaxVolumeFeedback; + StartupVolume = mixer.StartupVolume; + StartupVolumeFeedback = mixer.StartupVolumeFeedback; + PresetNumber = stream.PresetNumber; + RecallPreset = new Action(stream.RecallPreset); + } + } + public class Dmps3AudioOutputBase + { + public DMOutput Card { get; private set; } + public BoolOutputSig MasterMuteOffFeedBack { get; private set; } + public BoolOutputSig MasterMuteOnFeedBack { get; private set; } + public UShortInputSig MasterVolume { get; private set; } + public UShortOutputSig MasterVolumeFeedBack { get; private set; } + public BoolInputSig MasterVolumeUp { get; private set; } + public BoolInputSig MasterVolumeDown { get; private set; } + public BoolOutputSig SourceMuteOffFeedBack { get; private set; } + public BoolOutputSig SourceMuteOnFeedBack { get; private set; } + public UShortInputSig SourceLevel { get; private set; } + public UShortOutputSig SourceLevelFeedBack { get; private set; } + public BoolInputSig SourceLevelUp { get; private set; } + public BoolInputSig SourceLevelDown { get; private set; } + + public Action MasterMuteOff { get; private set; } + public Action MasterMuteOn { get; private set; } + public Action SourceMuteOff { get; private set; } + public Action SourceMuteOn { get; private set; } + + public Dmps3AudioOutputBase(Card.Dmps3OutputBase card) + { + Card = card; + MasterMuteOffFeedBack = card.MasterMuteOffFeedBack; + MasterMuteOnFeedBack = card.MasterMuteOnFeedBack; + MasterVolume = card.MasterVolume; + MasterVolumeFeedBack = card.MasterVolumeFeedBack; + MasterVolumeUp = card.MasterVolumeUp; + MasterVolumeDown = card.MasterVolumeDown; + SourceMuteOffFeedBack = card.SourceMuteOffFeedBack; + SourceMuteOnFeedBack = card.SourceMuteOnFeedBack; + SourceLevel = card.SourceLevel; + SourceLevelFeedBack = card.SourceLevelFeedBack; + SourceLevelUp = card.SourceLevelUp; + SourceLevelDown = card.SourceLevelDown; + + MasterMuteOff = new Action(card.MasterMuteOff); + MasterMuteOn = new Action(card.MasterMuteOn); + SourceMuteOff = new Action(card.SourceMuteOff); + SourceMuteOn = new Action(card.SourceMuteOn); + } + + public Dmps3AudioOutputBase(Card.Dmps3DmHdmiAudioOutput.Dmps3AudioOutputStream stream) + { + MasterMuteOffFeedBack = stream.MasterMuteOffFeedBack; + MasterMuteOnFeedBack = stream.MasterMuteOnFeedBack; + MasterVolume = stream.MasterVolume; + MasterVolumeFeedBack = stream.MasterVolumeFeedBack; + MasterVolumeUp = stream.MasterVolumeUp; + MasterVolumeDown = stream.MasterVolumeDown; + SourceMuteOffFeedBack = stream.SourceMuteOffFeedBack; + SourceMuteOnFeedBack = stream.SourceMuteOnFeedBack; + SourceLevel = stream.SourceLevel; + SourceLevelFeedBack = stream.SourceLevelFeedBack; + SourceLevelUp = stream.SourceLevelUp; + SourceLevelDown = stream.SourceLevelDown; + + MasterMuteOff = new Action(stream.MasterMuteOff); + MasterMuteOn = new Action(stream.MasterMuteOn); + SourceMuteOff = new Action(stream.SourceMuteOff); + SourceMuteOn = new Action(stream.SourceMuteOn); + } + + public Dmps3AudioOutputBase(Card.Dmps3DmHdmiAudioOutput.Dmps3DmHdmiOutputStream stream) + { + MasterMuteOffFeedBack = stream.MasterMuteOffFeedBack; + MasterMuteOnFeedBack = stream.MasterMuteOnFeedBack; + MasterVolume = stream.MasterVolume; + MasterVolumeFeedBack = stream.MasterVolumeFeedBack; + MasterVolumeUp = stream.MasterVolumeUp; + MasterVolumeDown = stream.MasterVolumeDown; + SourceMuteOffFeedBack = stream.SourceMuteOffFeedBack; + SourceMuteOnFeedBack = stream.SourceMuteOnFeedBack; + SourceLevel = stream.SourceLevel; + SourceLevelFeedBack = stream.SourceLevelFeedBack; + SourceLevelUp = stream.SourceLevelUp; + SourceLevelDown = stream.SourceLevelDown; + + MasterMuteOff = new Action(stream.MasterMuteOff); + MasterMuteOn = new Action(stream.MasterMuteOn); + SourceMuteOff = new Action(stream.SourceMuteOff); + SourceMuteOn = new Action(stream.SourceMuteOn); + } + } + public enum eDmpsLevelType { Master, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs index 49b5c1c5..70465783 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs @@ -15,7 +15,7 @@ namespace PepperDash.Essentials.DM /// /// /// - public class DmpsDigitalOutputController : Device, IRoutingNumericWithFeedback, IHasFeedback + public class DmpsDigitalOutputController : Device, IRoutingNumeric, IHasFeedback { public Card.Dmps3OutputBase OutputCard { get; protected set; } @@ -161,11 +161,5 @@ namespace PepperDash.Essentials.DM } #endregion - - #region IRoutingFeedback Members - - public event EventHandler NumericSwitchChange; - - #endregion } } \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index 55c49a96..074880e6 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -418,17 +418,11 @@ namespace PepperDash.Essentials.DM private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap) { - if (Global.ControlSystemIsDmps4kType) + if (Global.ControlSystemIsDmps4k3xxType) { - //DMPS-4K audio inputs 1-5 are aux inputs, add them after regular dm cards - for (ushort i = 1; i <= 5; i++) - { - trilist.StringInput[joinMap.InputAudioNames.JoinNumber + i - 1 + (ushort)Dmps.SwitcherInputs.Count].StringValue = String.Format("Aux Input {0}", i); - } - //Add DMPS-4K mixer input names to end of inputs - trilist.StringInput[joinMap.InputAudioNames.JoinNumber + (uint)Dmps.SwitcherInputs.Count + 5].StringValue = "Digital Mixer 1"; - trilist.StringInput[joinMap.InputAudioNames.JoinNumber + (uint)Dmps.SwitcherInputs.Count + 6].StringValue = "Digital Mixer 2"; + trilist.StringInput[joinMap.InputAudioNames.JoinNumber + (uint)Dmps.SwitcherInputs.Count + 4].StringValue = "Digital Mixer 1"; + trilist.StringInput[joinMap.InputAudioNames.JoinNumber + (uint)Dmps.SwitcherInputs.Count + 5].StringValue = "Digital Mixer 2"; } for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++) { @@ -445,9 +439,19 @@ namespace PepperDash.Essentials.DM if (InputNameFeedbacks.ContainsKey(ioSlot) && InputNameFeedbacks[ioSlot] != null) { - InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); - InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputVideoNames.JoinNumber + ioSlotJoin]); - InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin]); + if (Dmps.SwitcherInputs[ioSlot] is Card.Dmps3AnalogAudioInput) + { + for (uint j = ioSlot; j < ioSlot + 5; j++) + { + InputNameFeedbacks[j].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + j - 1]); + } + } + else + { + InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); + InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputVideoNames.JoinNumber + ioSlotJoin]); + InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin]); + } } trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s => @@ -509,7 +513,7 @@ namespace PepperDash.Essentials.DM }); AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() => { - if (!Global.ControlSystemIsDmps4kType) + if (!Global.ControlSystemIsDmps4k3xxType) { if (outputCard.AudioOutFeedback != null) { @@ -526,9 +530,9 @@ namespace PepperDash.Essentials.DM if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 0) return 0; else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 1) - return (ushort)Dmps.SwitcherInputs.Count + 6; + return (ushort)Dmps.SwitcherInputs.Count + 5; else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 2) - return (ushort)Dmps.SwitcherInputs.Count + 7; + return (ushort)Dmps.SwitcherInputs.Count + 6; else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 3) return (ushort)outputCard.VideoOutFeedback.Number; else @@ -552,7 +556,7 @@ namespace PepperDash.Essentials.DM else if ((ushort)outputCard.AudioOutSourceFeedback <= 5) { //Move analog inputs to after regular dm cards - return (ushort)outputCard.AudioOutSourceFeedback + (ushort)Dmps.SwitcherInputs.Count; + return (ushort)outputCard.AudioOutSourceFeedback + (ushort)Dmps.SwitcherInputs.Count - 1; } else { @@ -586,7 +590,7 @@ namespace PepperDash.Essentials.DM }); OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => { - if (!Global.ControlSystemIsDmps4kType) + if (!Global.ControlSystemIsDmps4k3xxType) { if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null) { @@ -692,7 +696,6 @@ namespace PepperDash.Essentials.DM else if (inputCard is Card.Dmps3HdmiInput) { var hdmiInputCard = inputCard as Card.Dmps3HdmiInput; - var cecPort = hdmiInputCard.HdmiInputPort; AddInputPortWithDebug(number, string.Format("HdmiIn{0}", number), eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, cecPort); @@ -724,17 +727,37 @@ namespace PepperDash.Essentials.DM else if (inputCard is Card.Dmps3DmInput) { var hdmiInputCard = inputCard as Card.Dmps3DmInput; - var cecPort = hdmiInputCard.DmInputPort; AddInputPortWithDebug(number, string.Format("DmIn{0}", number), eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, cecPort); } + else if (inputCard is Card.Dmps3VgaInput) + { + AddInputPortWithDebug(number, string.Format("VgaIn{0}", number), eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Vga); + } else if (inputCard is Card.Dmps3AirMediaInput) { - var airMediaInputCard = inputCard as Card.Dmps3AirMediaInput; - AddInputPortWithDebug(number, string.Format("AirMediaIn{0}", number), eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Streaming); } + else if (inputCard is Card.Dmps3AnalogAudioInput) + { + for (uint i = 0; i <= 4; i++) + { + uint j = i + 1; + uint input = i + number; + InputNameFeedbacks[input] = new StringFeedback(() => + { + if (InputNames.ContainsKey(input)) + { + return InputNames[input]; + } + else + { + return String.Format("Aux Input {0}", j); + } + }); + } + } } @@ -796,7 +819,6 @@ namespace PepperDash.Essentials.DM else if (outputCard is Card.Dmps3DmOutput) { AddDmOutputPort(number); - var audioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number), string.Format("Dm Audio Output {0}", number), outputCard as Card.Dmps3DmOutput); DeviceManager.AddDevice(audioOutput); } @@ -807,6 +829,19 @@ namespace PepperDash.Essentials.DM DigitalAudioOutputs.Add(number, audioOutput); DeviceManager.AddDevice(audioOutput); } + else if (outputCard is Card.Dmps3DmHdmiAudioOutput) + { + var hdmiOutputCard = outputCard as Card.Dmps3DmHdmiAudioOutput; + var cecPort = hdmiOutputCard.HdmiOutputPort; + AddHdmiOutputPort(number, cecPort); + AddDmOutputPort(number); + AddAudioOnlyOutputPort(number, "Program"); + + var audioOutput = new DmpsAudioOutputController(string.Format("processor-programAudioOutput", number), string.Format("Program Audio Output {0}", number), hdmiOutputCard, hdmiOutputCard.AudioOutputStream); + DeviceManager.AddDevice(audioOutput); + var digitalAudioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number), string.Format("Hdmi Audio Output {0}", number), hdmiOutputCard, hdmiOutputCard.DmHdmiOutputStream); + DeviceManager.AddDevice(digitalAudioOutput); + } else if (outputCard is Card.Dmps3ProgramOutput) { AddAudioOnlyOutputPort(number, "Program"); @@ -1041,7 +1076,7 @@ namespace PepperDash.Essentials.DM } else if (args.EventId == DMOutputEventIds.AudioOutEventId) { - if (!Global.ControlSystemIsDmps4kType) + if (!Global.ControlSystemIsDmps4k3xxType) { if (outputCard != null && outputCard.AudioOutFeedback != null) { @@ -1180,7 +1215,7 @@ namespace PepperDash.Essentials.DM if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) { - if(!Global.ControlSystemIsDmps4kType) + if (!Global.ControlSystemIsDmps4k3xxType) { output.AudioOut = input; } @@ -1198,7 +1233,7 @@ namespace PepperDash.Essentials.DM else if (Dmps.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) output.AudioOutSource = eDmps34KAudioOutSource.AirMedia9; } - else if (input.Number <= Dmps.SwitcherInputs.Count) + else if (input.Number < Dmps.SwitcherInputs.Count) { //Shift video inputs by 5 for weird DMPS3-4K indexing output.AudioOutSource = (eDmps34KAudioOutSource)(input.Number + 5); @@ -1206,7 +1241,7 @@ namespace PepperDash.Essentials.DM else { //Shift analog inputs back to inputs 1-5 - output.AudioOutSource = (eDmps34KAudioOutSource)(input.Number - Dmps.SwitcherInputs.Count); + output.AudioOutSource = (eDmps34KAudioOutSource)(input.Number - Dmps.SwitcherInputs.Count + 1); } } } @@ -1261,7 +1296,7 @@ namespace PepperDash.Essentials.DM else if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) { //Special case for DMPS-4K digital audio output - if (Global.ControlSystemIsDmps4kType) + if (Global.ControlSystemIsDmps4k3xxType) { if (DigitalAudioOutputs.ContainsKey(outputSelector)) { @@ -1269,37 +1304,37 @@ namespace PepperDash.Essentials.DM { DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(0, 0, eRoutingSignalType.Audio); } - else if (inputSelector <= Dmps.SwitcherInputs.Count) //DMPS-4K video inputs, set to audio follows video + else if (inputSelector < Dmps.SwitcherInputs.Count) //DMPS-4K video inputs, set to audio follows video { DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(3, 0, eRoutingSignalType.Audio); //Force video route since it is now set so audio follows video ExecuteNumericSwitch(inputSelector, outputSelector, eRoutingSignalType.Video); } - else if (inputSelector == Dmps.SwitcherInputs.Count + 6) + else if (inputSelector == Dmps.SwitcherInputs.Count + 5) { //Set to mix 1 DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(1, 0, eRoutingSignalType.Audio); } - else if (inputSelector == Dmps.SwitcherInputs.Count + 7) + else if (inputSelector == Dmps.SwitcherInputs.Count + 6) { //Set to mix 2 DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(2, 0, eRoutingSignalType.Audio); } } - else if (inputSelector <= (Dmps.SwitcherInputs.Count + 5) && outputSelector <= Dmps.SwitcherOutputs.Count) + else if (inputSelector <= (Dmps.SwitcherInputs.Count + 4) && outputSelector <= Dmps.SwitcherOutputs.Count) { var output = Dmps.SwitcherOutputs[outputSelector] as DMOutput; if (inputSelector == 0) { output.AudioOutSource = eDmps34KAudioOutSource.NoRoute; } - else if(inputSelector > Dmps.SwitcherInputs.Count) + else if(inputSelector >= (Dmps.SwitcherInputs.Count)) { //Shift analog inputs back to inputs 1-5 - Debug.Console(1, this, "Attempting analog route input {0} to output {1}", inputSelector - Dmps.SwitcherInputs.Count, outputSelector); - output.AudioOutSource = (eDmps34KAudioOutSource)(inputSelector - Dmps.SwitcherInputs.Count); + Debug.Console(1, this, "Attempting analog route input {0} to output {1}", inputSelector - Dmps.SwitcherInputs.Count + 1, outputSelector); + output.AudioOutSource = (eDmps34KAudioOutSource)(inputSelector - Dmps.SwitcherInputs.Count + 1); } - else if (inputSelector <= Dmps.SwitcherInputs.Count) + else if (inputSelector < Dmps.SwitcherInputs.Count) { var input = Dmps.SwitcherInputs[inputSelector] as DMInput; if (input.CardInputOutputType == eCardInputOutputType.Dmps3AirMediaInput || input.CardInputOutputType == eCardInputOutputType.Dmps3AirMediaNoStreamingInput) From 794ba7e6dd6e2cf5bd91e7158cffc5f54ee0dd76 Mon Sep 17 00:00:00 2001 From: Rodney Driscoll Date: Fri, 17 Jun 2022 09:38:16 +1000 Subject: [PATCH 084/202] GetStringOutputSig and GetUShortOutputSig return --- .../SmartObjects/SubpageReferencList/SubpageReferenceList.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/SmartObjects/SubpageReferencList/SubpageReferenceList.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/SmartObjects/SubpageReferencList/SubpageReferenceList.cs index fe69e4ca..711a3cde 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/SmartObjects/SubpageReferencList/SubpageReferenceList.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/SmartObjects/SubpageReferencList/SubpageReferenceList.cs @@ -144,7 +144,7 @@ namespace PepperDash.Essentials.Core public UShortOutputSig GetUShortOutputSig(uint index, uint sigNum) { if (sigNum > UShortIncrement) return null; - return SRL.UShortOutput.FirstOrDefault(s => s.Name.Equals(GetBoolFeedbackSigName(index, sigNum))); + return SRL.UShortOutput.FirstOrDefault(s => s.Name.Equals(GetUShortOutputSigName(index, sigNum))); } /// @@ -159,7 +159,7 @@ namespace PepperDash.Essentials.Core public StringOutputSig GetStringOutputSig(uint index, uint sigNum) { if (sigNum > StringIncrement) return null; - return SRL.StringOutput.FirstOrDefault(s => s.Name.Equals(GetBoolFeedbackSigName(index, sigNum))); + return SRL.StringOutput.FirstOrDefault(s => s.Name.Equals(GetStringOutputSigName(index, sigNum))); } /// From 53c9f9e6640bc5143f4cd0f9c8922cc7b1d29439 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Fri, 17 Jun 2022 14:42:51 -0400 Subject: [PATCH 085/202] Fixes issue where sometimes clear route doesn't work on DMPS3 --- .../Essentials_DM/Chassis/DmpsRoutingController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index 074880e6..17aa1b1d 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -1357,7 +1357,7 @@ namespace PepperDash.Essentials.DM else if (inputSelector <= Dmps.SwitcherInputs.Count && outputSelector <= Dmps.SwitcherOutputs.Count) { var output = Dmps.SwitcherOutputs[outputSelector] as DMOutput; - var input = Dmps.SwitcherInputs[inputSelector] as DMInput; + var input = inputSelector == 0 ? null : Dmps.SwitcherInputs[inputSelector] as DMInput; output.AudioOut = input; } } From 4c9a470885d8a71878666cfffba11f6edcb5c92d Mon Sep 17 00:00:00 2001 From: jta Date: Mon, 13 Jun 2022 13:22:23 -0500 Subject: [PATCH 086/202] Fix IBasicVolumeControls fix: revert a change that split the interface but could break backwards compatibility #955 --- .../Devices/IVolumeAndAudioInterfaces.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs index 254eada2..c5fc185a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs @@ -9,8 +9,11 @@ namespace PepperDash.Essentials.Core /// /// Defines minimal volume and mute control methods /// - public interface IBasicVolumeControls : IHasVolumeControl, IHasMuteControl + public interface IBasicVolumeControls { + void VolumeUp(bool pressRelease); + void VolumeDown(bool pressRelease); + void MuteToggle(); } /// From 38c4a540a98ae2e5e5e870f00fb161fa8f3239fc Mon Sep 17 00:00:00 2001 From: jta Date: Mon, 13 Jun 2022 13:01:04 -0500 Subject: [PATCH 087/202] fix for IBasicVolumeWithFeedback fix: for a change that split the interface but could break backwards compatibility #955 --- .../Devices/IVolumeAndAudioInterfaces.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs index c5fc185a..c8a5df39 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs @@ -55,8 +55,13 @@ namespace PepperDash.Essentials.Core /// /// Adds feedback and direct volume level set to IBasicVolumeControls /// - public interface IBasicVolumeWithFeedback : IBasicVolumeControls, IHasVolumeControlWithFeedback, IHasMuteControlWithFeedback + public interface IBasicVolumeWithFeedback : IBasicVolumeControls { + BoolFeedback MuteFeedback { get; } + void MuteOn(); + void MuteOff(); + void SetVolume(ushort level); + IntFeedback VolumeLevelFeedback { get; } } /// From d849e4185cbac3685c82a3f40926e64173411d22 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Mon, 27 Jun 2022 09:35:38 -0400 Subject: [PATCH 088/202] Fixes clear audio route on DMPS3-4K-150. Fixes output names on join map for DMPS3-4K-150 --- .../Essentials_DM/Chassis/DmpsAudioOutputController.cs | 2 +- .../Essentials_DM/Chassis/DmpsRoutingController.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs index c3ed2354..c0f0ca65 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs @@ -327,7 +327,7 @@ namespace PepperDash.Essentials.DM Output.PresetNumber.UShortValue = preset; Output.RecallPreset(); - if (!Global.ControlSystemIsDmps4kType) + if (!Global.ControlSystemIsDmps4k3xxType) { //Recall startup volume for main volume level as DMPS3(non-4K) presets don't affect the main volume RecallStartupVolume(); diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index 17aa1b1d..a3092f71 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -386,7 +386,8 @@ namespace PepperDash.Essentials.DM if (Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3DmOutput || Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3DmOutputBackend || Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3HdmiOutput || - Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3HdmiOutputBackend) + Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3HdmiOutputBackend || + Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3DmHdmiAudioOutput) { OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputVideoNames.JoinNumber + ioSlotJoin]); OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); From d8ac302f1c72bae6a14d1ba877eb5a1052c020c8 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Mon, 11 Jul 2022 17:30:51 -0500 Subject: [PATCH 089/202] [feature] - Create and Implement IConvertiblePreset within the VideoCodec and the VideoCodec.Cisco namespaces RESOLVES #966 --- .../Essentials Devices Common.csproj | 1 + .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 15 ++++--- .../VideoCodec/CiscoCodec/RoomPresets.cs | 39 ++++--------------- .../VideoCodec/CiscoCodec/xStatus.cs | 26 +++++++++++-- .../VideoCodec/IConvertiblePreset.cs | 9 +++++ 5 files changed, 49 insertions(+), 41 deletions(-) create mode 100644 essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index fe4d5f61..547e8711 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -108,6 +108,7 @@ + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index c9e584d3..581e34e5 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -1023,20 +1023,25 @@ ConnectorID: {2}" if (tempPresets.Count > 0) { // Create temporary list to store the existing items from the CiscoCodecStatus.RoomPreset collection - List existingRoomPresets = new List(); + var existingRoomPresets = new List(); // Add the existing items to the temporary list existingRoomPresets.AddRange(CodecStatus.Status.RoomPreset); // Populate the CodecStatus object (this will append new values to the RoomPreset collection JsonConvert.PopulateObject(response, CodecStatus); - JObject jResponse = JObject.Parse(response); + var jResponse = JObject.Parse(response); + + List convertedRoomPresets = + existingRoomPresets.Select(a => (CiscoCodecStatus.RoomPreset) a).ToList(); IList roomPresets = jResponse["Status"]["RoomPreset"].Children().ToList(); // Iterate the new items in this response agains the temporary list. Overwrite any existing items and add new ones. - foreach (var preset in tempPresets) + foreach (var camPreset in tempPresets) { + var preset = camPreset as CiscoCodecStatus.RoomPreset; + if (preset == null) continue; // First fine the existing preset that matches the id - var existingPreset = existingRoomPresets.FirstOrDefault(p => p.id.Equals(preset.id)); + var existingPreset = convertedRoomPresets.FirstOrDefault(p => p.id.Equals(preset.id)); if (existingPreset != null) { Debug.Console(1, this, "Existing Room Preset with ID: {0} found. Updating.", existingPreset.id); @@ -1068,7 +1073,7 @@ ConnectorID: {2}" CodecStatus.Status.RoomPreset = existingRoomPresets; // Generecise the list - NearEndPresets = RoomPresets.GetGenericPresets(CodecStatus.Status.RoomPreset); + NearEndPresets = RoomPresets.GetGenericPresets(existingRoomPresets).Select(a =>(CodecRoomPreset)a).ToList(); var handler = CodecRoomPresetsListHasChanged; if (handler != null) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs index b6327d52..1cf9acdf 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs @@ -1,14 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Essentials.Core.Presets; -using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; namespace PepperDash.Essentials.Devices.Common.VideoCodec { @@ -33,39 +28,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public static class RoomPresets { /// - /// Converts Cisco RoomPresets to generic CameraPresets + /// Converts non-generic RoomPresets to generic CameraPresets /// /// /// - public static List GetGenericPresets(List presets) + public static List GetGenericPresets(List presets) { - var cameraPresets = new List(); + Debug.Console(2, "Presets List:"); - if (Debug.Level > 0) - { - Debug.Console(1, "Presets List:"); - } - foreach (CiscoCodecStatus.RoomPreset preset in presets) - { - try - { - var cameraPreset = new CodecRoomPreset(UInt16.Parse(preset.id), preset.Description.Value, preset.Defined.BoolValue, true); - - cameraPresets.Add(cameraPreset); - - if (Debug.Level > 0) - { - Debug.Console(1, "Added Preset ID: {0}, Description: {1}, IsDefined: {2}, isDefinable: {3}", cameraPreset.ID, cameraPreset.Description, cameraPreset.Defined, cameraPreset.IsDefinable); - } - } - catch (Exception e) - { - Debug.Console(2, "Unable to convert preset: {0}. Error: {1}", preset.id, e); - } - } - - return cameraPresets; + return + presets.Select(preset => preset.ReturnConvertedCodecPreset()) + .Where(newPreset => newPreset != null) + .ToList(); } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index 5bde30ff..2c84cba8 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -9,6 +9,7 @@ using Newtonsoft.Json.Linq; using PepperDash.Core; using PepperDash.Essentials.Devices.Common.VideoCodec.CiscoCodec; +using PepperDash.Essentials.Core.Presets; namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { @@ -2185,7 +2186,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } } - public class RoomPreset + public class RoomPreset : IConvertiblePreset { public string id { get; set; } public Defined Defined { get; set; } @@ -2198,7 +2199,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco Description = new Description2(); Type = new Type5(); } - } + + public PresetBase ReturnConvertedCodecPreset() + { + try + { + var preset = new CodecRoomPreset(UInt16.Parse(id), Description.Value, Defined.BoolValue, true); + + Debug.Console(2, "Preset ID {0} Converted from Cisco Codec Preset to Essentials Preset"); + + return preset; + } + catch (Exception e) + { + Debug.Console(2, "Unable to convert preset: {0}. Error: {1}", id, e); + return null; + } + } +} @@ -2222,7 +2240,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public Proximity Proximity { get; set; } public RoomAnalytics RoomAnalytics { get; set; } - public List RoomPreset { get; set; } + public List RoomPreset { get; set; } public SIP SIP { get; set; } public Security Security { get; set; } @@ -2239,7 +2257,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco Standby = new Standby(); Cameras = new Cameras(); RoomAnalytics = new RoomAnalytics(); - RoomPreset = new List(); + RoomPreset = new List(); Conference = new Conference2(); SystemUnit = new SystemUnit(); Video = new Video(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs new file mode 100644 index 00000000..7c3695aa --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs @@ -0,0 +1,9 @@ +using PepperDash.Essentials.Core.Presets; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec +{ + public interface IConvertiblePreset + { + PresetBase ReturnConvertedCodecPreset(); + } +} \ No newline at end of file From b505ad467b8e76ca2033b1ee8c03d85464f3d9b4 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Tue, 12 Jul 2022 12:34:28 -0500 Subject: [PATCH 090/202] [feature] added IHasCodecLayoutsAvailable interface and associated bridge linking methods Modifies #966 --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 59 +++++++++++++++++++ .../VideoCodec/Interfaces/IHasCodecLayouts.cs | 10 ++++ .../VideoCodec/VideoCodecBase.cs | 13 ++++ 3 files changed, 82 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index b26471dd..9e982700 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -1576,6 +1576,36 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); + [JoinName("AvailableLayoutsFb")] + public JoinDataComplete AvailableLayoutsFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "xSig of all available layouts", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelectLayout")] + public JoinDataComplete SelectLayout = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Select Layout by string", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + + [JoinName("CurrentParticipants")] public JoinDataComplete CurrentParticipants = new JoinDataComplete( new JoinData @@ -3014,6 +3044,35 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); + [JoinName("AvailableLayoutsFb")] + public JoinDataComplete AvailableLayoutsFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "xSig of all available layouts", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelectLayout")] + public JoinDataComplete SelectLayout = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Select Layout by string", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentParticipants")] public JoinDataComplete CurrentParticipants = new JoinDataComplete( new JoinData diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs index ef0bf2bd..454c3f3e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs @@ -22,6 +22,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec void MinMaxLayoutToggle(); } + /// + /// Defines the required elements for layout control with direct layout selection + /// + public interface IHasCodecLayoutsAvailable : IHasCodecLayouts + { + StringFeedback AvailableLocalLayoutsFeedback { get; set; } + Dictionary AvailableLocalLayouts { get; set; } + void LocalLayoutSet(string layoutId); + } + /// /// Defines the requirements for Zoom Room layout control /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 593472e9..19d48be7 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -370,6 +370,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecCameraLayoutsToApi(codec as IHasCodecLayouts, trilist, joinMap); } + if (codec is IHasCodecLayoutsAvailable) + { + LinkVideoCodecAvailableLayoutsToApi(codec as IHasCodecLayoutsAvailable, trilist, joinMap); + } + if (codec is IHasSelfviewPosition) { LinkVideoCodecSelfviewPositionToApi(codec as IHasSelfviewPosition, trilist, joinMap); @@ -1471,6 +1476,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentLayoutStringFb.JoinNumber]); } + private void LinkVideoCodecAvailableLayoutsToApi(IHasCodecLayoutsAvailable codec, BasicTriList trilist, + VideoCodecControllerJoinMap joinMap) + { + codec.AvailableLocalLayoutsFeedback.LinkInputSig(trilist.StringInput[joinMap.AvailableLayoutsFb.JoinNumber]); + + trilist.SetStringSigAction(joinMap.SelectLayout.JoinNumber, codec.LocalLayoutSet); + } + private void LinkVideoCodecCameraModeToApi(IHasCameraAutoMode codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { trilist.SetSigFalseAction(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeOn); From 9ecaec55840f9df393c29824f6e0399943a246fc Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Tue, 12 Jul 2022 15:02:22 -0500 Subject: [PATCH 091/202] [fix] slight change to move CodecCommandWithLabel into the VideoCodec namespace and modify the IHasCodecLayoutsAvailable interface to utilize this class Modifies #966 --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 14 -------------- .../VideoCodec/Interfaces/IHasCodecLayouts.cs | 2 +- .../VideoCodec/Interfaces/IHasSelfviewPosition.cs | 2 +- .../VideoCodec/Interfaces/IHasSelfviewSize.cs | 2 +- .../VideoCodec/VideoCodecBase.cs | 15 +++++++++++++++ 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 581e34e5..669a09ac 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -2470,20 +2470,6 @@ ConnectorID: {2}" } - /// - /// Represents a codec command that might need to have a friendly label applied for UI feedback purposes - /// - public class CodecCommandWithLabel - { - public string Command { get; set; } - public string Label { get; set; } - - public CodecCommandWithLabel(string command, string label) - { - Command = command; - Label = label; - } - } /// /// Tracks the initial sycnronization state of the codec when making a connection diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs index 454c3f3e..3368b1d2 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs @@ -28,7 +28,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public interface IHasCodecLayoutsAvailable : IHasCodecLayouts { StringFeedback AvailableLocalLayoutsFeedback { get; set; } - Dictionary AvailableLocalLayouts { get; set; } + List AvailableLocalLayouts { get; set; } void LocalLayoutSet(string layoutId); } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs index 5360b80a..d0ba25fd 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs @@ -1,5 +1,5 @@ using PepperDash.Essentials.Core; -using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; +using PepperDash.Essentials.Devices.Common.VideoCodec; namespace PepperDash.Essentials.Core.DeviceTypeInterfaces { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewSize.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewSize.cs index 91ac3ec8..4103fa0e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewSize.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasSelfviewSize.cs @@ -1,4 +1,4 @@ -using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; +using PepperDash.Essentials.Devices.Common.VideoCodec; namespace PepperDash.Essentials.Core.DeviceTypeInterfaces { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 19d48be7..202a6a5b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1995,4 +1995,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } } } + /// + /// Represents a codec command that might need to have a friendly label applied for UI feedback purposes + /// + public class CodecCommandWithLabel + { + public string Command { get; set; } + public string Label { get; set; } + + public CodecCommandWithLabel(string command, string label) + { + Command = command; + Label = label; + } + } + } \ No newline at end of file From 96ec2cbe49240a71515bd16eeff6e302ad96c6c7 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Tue, 12 Jul 2022 15:38:48 -0500 Subject: [PATCH 092/202] [Fix] - Updated IHasCodecLayoutsAvailable setters [Adjusts] #966 --- .../VideoCodec/Interfaces/IHasCodecLayouts.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs index 3368b1d2..a7b68501 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs @@ -27,8 +27,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public interface IHasCodecLayoutsAvailable : IHasCodecLayouts { - StringFeedback AvailableLocalLayoutsFeedback { get; set; } - List AvailableLocalLayouts { get; set; } + StringFeedback AvailableLocalLayoutsFeedback { get; } + List AvailableLocalLayouts { get; } void LocalLayoutSet(string layoutId); } From 9c8bb66c5e21f204f66c8c3fd9899ab23895cc1c Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Tue, 12 Jul 2022 15:38:48 -0500 Subject: [PATCH 093/202] [Fix] - Updated IHasCodecLayoutsAvailable setters [Adjusts] #966 --- .../VideoCodec/Interfaces/IHasCodecLayouts.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs index 3368b1d2..f571e40c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs @@ -27,9 +27,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public interface IHasCodecLayoutsAvailable : IHasCodecLayouts { - StringFeedback AvailableLocalLayoutsFeedback { get; set; } - List AvailableLocalLayouts { get; set; } - void LocalLayoutSet(string layoutId); + event EventHandler AvailableLayoutsChanged; + + StringFeedback AvailableLocalLayoutsFeedback { get; } + List AvailableLocalLayouts { get; } + void LocalLayoutSet(string layout); + void LocalLayoutSet(CodecCommandWithLabel layout); + + } + + public class AvailableLayoutChangedEventArgs : EventArgs + { + public List AvailableLayouts { get; set; } } /// From 04e8508c0c5c46436b25e6d32d30101ae51af060 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 15 Jul 2022 11:38:19 -0500 Subject: [PATCH 094/202] fix: requested changes for PR #967 --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 2 +- .../VideoCodec/CiscoCodec/RoomPresets.cs | 8 +++----- .../VideoCodec/CiscoCodec/xStatus.cs | 2 +- .../VideoCodec/IConvertiblePreset.cs | 2 +- .../VideoCodec/VideoCodecBase.cs | 4 ++-- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 669a09ac..0bca7181 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -1073,7 +1073,7 @@ ConnectorID: {2}" CodecStatus.Status.RoomPreset = existingRoomPresets; // Generecise the list - NearEndPresets = RoomPresets.GetGenericPresets(existingRoomPresets).Select(a =>(CodecRoomPreset)a).ToList(); + NearEndPresets = existingRoomPresets.GetGenericPresets(); var handler = CodecRoomPresetsListHasChanged; if (handler != null) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs index 1cf9acdf..4fec0d89 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs @@ -32,14 +32,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// /// /// - public static List GetGenericPresets(List presets) + public static List GetGenericPresets(this List presets) { - Debug.Console(2, "Presets List:"); - - return - presets.Select(preset => preset.ReturnConvertedCodecPreset()) + presets.Select(preset => preset.ConvertCodecPreset()) .Where(newPreset => newPreset != null) + .Cast() .ToList(); } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index 2c84cba8..23e8c6ab 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -2200,7 +2200,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco Type = new Type5(); } - public PresetBase ReturnConvertedCodecPreset() + public PresetBase ConvertCodecPreset() { try { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs index 7c3695aa..f6f3f74f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs @@ -4,6 +4,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { public interface IConvertiblePreset { - PresetBase ReturnConvertedCodecPreset(); + PresetBase ConvertCodecPreset(); } } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 202a6a5b..c7579f0b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -2000,8 +2000,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public class CodecCommandWithLabel { - public string Command { get; set; } - public string Label { get; set; } + public string Command { get; private set; } + public string Label { get; private set; } public CodecCommandWithLabel(string command, string label) { From 5a4cc2fd39210d5ccf8066482e750baa243239cc Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 15 Jul 2022 17:40:48 -0500 Subject: [PATCH 095/202] fix:console commands for Secrets Management Modified --- .../Config/DeviceConfig.cs | 131 +++++++++--------- .../Devices/ReconfigurableDevice.cs | 2 +- .../Secrets/CrestronSecretsProvider.cs | 21 +-- 3 files changed, 79 insertions(+), 75 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs index 1d9ed1c2..5c1ee54c 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs @@ -1,35 +1,35 @@ -using System; -using System.Collections.Generic; -using Crestron.SimplSharp; -using Crestron.SimplSharp.CrestronIO; -using Crestron.SimplSharpPro; - -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using PepperDash.Core; -using PepperDash.Essentials.Core; - -namespace PepperDash.Essentials.Core.Config -{ - public class DeviceConfig - { - [JsonProperty("key")] - public string Key { get; set; } - - [JsonProperty("uid")] - public int Uid { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("group")] - public string Group { get; set; } - - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("properties")] - [JsonConverter(typeof(DevicePropertiesConverter))] +using System; +using System.Collections.Generic; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronIO; +using Crestron.SimplSharpPro; + +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Core.Config +{ + public class DeviceConfig + { + [JsonProperty("key")] + public string Key { get; set; } + + [JsonProperty("uid")] + public int Uid { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("group")] + public string Group { get; set; } + + [JsonProperty("type")] + public string Type { get; set; } + + [JsonProperty("properties")] + [JsonConverter(typeof(DevicePropertiesConverter))] public JToken Properties { get; set; } public DeviceConfig(DeviceConfig dc) @@ -39,39 +39,42 @@ namespace PepperDash.Essentials.Core.Config Name = dc.Name; Group = dc.Group; Type = dc.Type; - Properties = JToken.FromObject(dc.Properties); + + Properties = JToken.Parse(dc.Properties.ToString()); + + //Properties = JToken.FromObject(dc.Properties); } public DeviceConfig() {} - } - - /// - /// - /// - public class DevicePropertiesConverter : JsonConverter - { - - public override bool CanConvert(Type objectType) - { - return objectType == typeof(JToken); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - return JToken.ReadFrom(reader); - } - - public override bool CanWrite - { - get - { - return false; - } - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException("SOD OFF HOSER"); - } - } + } + + /// + /// + /// + public class DevicePropertiesConverter : JsonConverter + { + + public override bool CanConvert(Type objectType) + { + return objectType == typeof(JToken); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + return JToken.ReadFrom(reader); + } + + public override bool CanWrite + { + get + { + return false; + } + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException("SOD OFF HOSER"); + } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs index 3239e192..a54f728d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs @@ -59,7 +59,7 @@ namespace PepperDash.Essentials.Core.Devices /// /// Used by the extending class to allow for any custom actions to be taken (tell the ConfigWriter to write config, etc) /// - /// + /// protected virtual void CustomSetConfig(DeviceConfig config) { ConfigWriter.UpdateDeviceConfig(config); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs index 3e0a5964..0c531a08 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs @@ -36,21 +36,22 @@ namespace PepperDash.Essentials.Core public bool SetSecret(string key, object value) { var secret = value as string; + CrestronDataStore.CDS_ERROR returnCode; + if (String.IsNullOrEmpty(secret)) { - Debug.Console(2, this, "Unable to set secret for {0}:{1} - value is empty.", Key, key); - return false; + returnCode = CrestronDataStoreStatic.clearLocal(key); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) return true; } - var setErrorCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret); - switch (setErrorCode) + + else { - case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: - Debug.Console(1, this,"Secret Successfully Set for {0}:{1}", Key, key); - return true; - default: - Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, setErrorCode.ToString()); - return false; + returnCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) return true; } + + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString()); + return false; } /// From 4037fad26b1864d1306d6bb53e8b3294083d0d58 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Mon, 18 Jul 2022 15:05:08 -0500 Subject: [PATCH 096/202] fix: updated erroneous console responses for Secrets Providers refactor: updated method by which the Factories assess secret objects refactor: updated 'SecretsManager' console responses feat: added 'secretproviderlist' console command feat: added 'secretproviderinfo' console command feat: added 'CrestronGlobalSecretsProvider' feat: Added 'Description' property to 'ISecretProvider' feat: added 'TestSecret' method to 'ISecretProvider' docs: added xml comments to 'ISecretProvider' docs: added xml comments to 'ISecret' refactor: cleaned up crestron default secrets provider classes refactor: moved 'CrestronSecret' to its own class file refactor: overhauled all secrets-related console commands --- .../PepperDash_Essentials_Core.csproj | 4 +- .../Secrets/CrestronGlobalSecretsProvider.cs | 102 +++++++++ ...der.cs => CrestronLocalSecretsProvider.cs} | 199 +++++++++--------- .../Secrets/CrestronSecret.cs | 28 +++ .../Secrets/Interfaces.cs | 34 +++ .../Secrets/SecretsManager.cs | 181 ++++++++++++---- 6 files changed, 406 insertions(+), 142 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronGlobalSecretsProvider.cs rename essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/{CrestronSecretsProvider.cs => CrestronLocalSecretsProvider.cs} (65%) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecret.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index c0903526..252a881e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -338,7 +338,9 @@ - + + + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronGlobalSecretsProvider.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronGlobalSecretsProvider.cs new file mode 100644 index 00000000..5adefd9e --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronGlobalSecretsProvider.cs @@ -0,0 +1,102 @@ +using System; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronDataStore; +using PepperDash.Core; + + +namespace PepperDash.Essentials.Core +{ + public class CrestronGlobalSecretsProvider : ISecretProvider + { + public string Key { get; set; } + //Added for reference + public string Description { get; private set; } + + public CrestronGlobalSecretsProvider(string key) + { + Key = key; + Description = String.Format("Default secret provider serving all local applications"); + + } + + static CrestronGlobalSecretsProvider() + { + //Added for future encrypted reference + var secureSupported = CrestronSecureStorage.Supported; + + CrestronDataStoreStatic.InitCrestronDataStore(); + if (secureSupported) + { + //doThingsFuture + } + } + + /// + /// Set secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// Secret Value + public bool SetSecret(string key, object value) + { + var secret = value as string; + CrestronDataStore.CDS_ERROR returnCode; + + if (String.IsNullOrEmpty(secret)) + { + returnCode = CrestronDataStoreStatic.clearGlobal(key); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + { + Debug.Console(0, this, "Successfully removed secret \"{0}\"", secret); + return true; + } + } + + else + { + returnCode = CrestronDataStoreStatic.SetGlobalStringValue(key, secret); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + { + Debug.Console(0, this, "Successfully set secret \"{0}\"", secret); + return true; + } + } + + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString()); + return false; + } + + /// + /// Retrieve secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// ISecret Object containing key, provider, and value + public ISecret GetSecret(string key) + { + string mySecret; + var getErrorCode = CrestronDataStoreStatic.GetGlobalStringValue(key, out mySecret); + + switch (getErrorCode) + { + case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: + Debug.Console(2, this, "Secret Successfully retrieved for {0}:{1}", Key, key); + return new CrestronSecret(key, mySecret, this); + default: + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}", + Key, key, getErrorCode.ToString()); + return null; + } + } + + /// + /// Determine if a secret is present within the provider without retrieving it + /// + /// Secret Key + /// bool if present + public bool TestSecret(string key) + { + string mySecret; + return CrestronDataStoreStatic.GetGlobalStringValue(key, out mySecret) == CrestronDataStore.CDS_ERROR.CDS_SUCCESS; + } + } + +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronLocalSecretsProvider.cs similarity index 65% rename from essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs rename to essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronLocalSecretsProvider.cs index 0c531a08..955c875c 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronLocalSecretsProvider.cs @@ -1,98 +1,103 @@ -using System; -using Crestron.SimplSharp; -using Crestron.SimplSharp.CrestronDataStore; -using PepperDash.Core; - - -namespace PepperDash.Essentials.Core -{ - public class CrestronSecretsProvider : ISecretProvider - { - public string Key { get; set; } - //Added for reference - private static readonly bool SecureSupported; - public CrestronSecretsProvider(string key) - { - Key = key; - } - - static CrestronSecretsProvider() - { - //Added for future encrypted reference - SecureSupported = CrestronSecureStorage.Supported; - - CrestronDataStoreStatic.InitCrestronDataStore(); - if (SecureSupported) - { - //doThingsFuture - } - } - - /// - /// Set secret for item in the CrestronSecretsProvider - /// - /// Secret Key - /// Secret Value - public bool SetSecret(string key, object value) - { - var secret = value as string; - CrestronDataStore.CDS_ERROR returnCode; - - if (String.IsNullOrEmpty(secret)) - { - returnCode = CrestronDataStoreStatic.clearLocal(key); - if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) return true; - } - - else - { - returnCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret); - if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) return true; - } - - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString()); - return false; - } - - /// - /// Retrieve secret for item in the CrestronSecretsProvider - /// - /// Secret Key - /// ISecret Object containing key, provider, and value - public ISecret GetSecret(string key) - { - string mySecret; - var getErrorCode = CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret); - - switch (getErrorCode) - { - case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: - Debug.Console(2, this, "Secret Successfully retrieved for {0}:{1}", Key, key); - return new CrestronSecret(key, mySecret, this); - default: - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}", - Key, key, getErrorCode.ToString()); - return null; - } - } - } - - /// - /// Special container class for CrestronSecret provider - /// - public class CrestronSecret : ISecret - { - public ISecretProvider Provider { get; private set; } - public string Key { get; private set; } - - public object Value { get; private set; } - - public CrestronSecret(string key, string value, ISecretProvider provider) - { - Key = key; - Value = value; - Provider = provider; - } - - } +using System; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronDataStore; +using PepperDash.Core; +using Crestron.SimplSharpPro; + + +namespace PepperDash.Essentials.Core +{ + public class CrestronLocalSecretsProvider : ISecretProvider + { + public string Key { get; set; } + //Added for reference + public string Description { get; private set; } + + + public CrestronLocalSecretsProvider(string key) + { + Key = key; + Description = String.Format("Default secret provider serving Essentials Application {0}", InitialParametersClass.ApplicationNumber); + } + + static CrestronLocalSecretsProvider() + { + //Added for future encrypted reference + var secureSupported = CrestronSecureStorage.Supported; + + CrestronDataStoreStatic.InitCrestronDataStore(); + if (secureSupported) + { + //doThingsFuture + } + } + + /// + /// Set secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// Secret Value + public bool SetSecret(string key, object value) + { + var secret = value as string; + CrestronDataStore.CDS_ERROR returnCode; + + if (String.IsNullOrEmpty(secret)) + { + returnCode = CrestronDataStoreStatic.clearLocal(key); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + { + Debug.Console(0, this, "Successfully removed secret \"{0}\"", secret); + return true; + } + } + + else + { + returnCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + { + Debug.Console(0, this, "Successfully set secret \"{0}\"", secret); + return true; + } + } + + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString()); + return false; + } + + /// + /// Retrieve secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// ISecret Object containing key, provider, and value + public ISecret GetSecret(string key) + { + string mySecret; + var getErrorCode = CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret); + + switch (getErrorCode) + { + case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: + Debug.Console(2, this, "Secret Successfully retrieved for {0}:{1}", Key, key); + return new CrestronSecret(key, mySecret, this); + default: + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}", + Key, key, getErrorCode.ToString()); + return null; + } + } + + /// + /// Determine if a secret is present within the provider without retrieving it + /// + /// Secret Key + /// bool if present + public bool TestSecret(string key) + { + string mySecret; + return CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret) == CrestronDataStore.CDS_ERROR.CDS_SUCCESS; + } + } + } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecret.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecret.cs new file mode 100644 index 00000000..27fbcdad --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecret.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Essentials.Core +{ + /// + /// Special container class for CrestronSecret provider + /// + public class CrestronSecret : ISecret + { + public ISecretProvider Provider { get; private set; } + public string Key { get; private set; } + + public object Value { get; private set; } + + public CrestronSecret(string key, string value, ISecretProvider provider) + { + Key = key; + Value = value; + Provider = provider; + } + + } + +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs index 43c6a230..e61ac208 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs @@ -7,9 +7,32 @@ namespace PepperDash.Essentials.Core /// public interface ISecretProvider : IKeyed { + /// + /// Set secret value for provider by key + /// + /// key of secret to set + /// value to set secret to + /// bool SetSecret(string key, object value); + /// + /// Return object containing secret from provider + /// + /// key of secret to retrieve + /// ISecret GetSecret(string key); + + /// + /// Verifies presence of secret + /// + /// key of secret to chek + /// + bool TestSecret(string key); + + /// + /// Description of the secrets provider + /// + string Description { get; } } /// @@ -17,8 +40,19 @@ namespace PepperDash.Essentials.Core /// public interface ISecret { + /// + /// Instance of ISecretProvider that the secret belongs to + /// ISecretProvider Provider { get; } + + /// + /// Key of the secret in the provider + /// string Key { get; } + + /// + /// Value of the secret + /// object Value { get; } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs index bcb46ff5..95a94a24 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; using Crestron.SimplSharp; using PepperDash.Core; - namespace PepperDash.Essentials.Core { public static class SecretsManager @@ -16,18 +16,28 @@ namespace PepperDash.Essentials.Core public static void Initialize() { - AddSecretProvider("default", new CrestronSecretsProvider("default")); + AddSecretProvider("default", new CrestronLocalSecretsProvider("default")); + + AddSecretProvider("CrestronGlobalSecrets", new CrestronGlobalSecretsProvider("CrestronGlobalSecrets")); CrestronConsole.AddNewConsoleCommand(SetSecretProcess, "setsecret", - "Adds secrets to secret provider", + "Adds secret to secrets provider", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(UpdateSecretProcess, "updatesecret", - "Updates secrets in secret provider", + "Updates secret in secrets provider", ConsoleAccessLevelEnum.AccessAdministrator); CrestronConsole.AddNewConsoleCommand(DeleteSecretProcess, "deletesecret", - "Deletes secrets in secret provider", + "Deletes secret from secrest provider", + ConsoleAccessLevelEnum.AccessAdministrator); + + CrestronConsole.AddNewConsoleCommand(ListProviders, "secretproviderlist", + "Return list of all valid secrets providers", + ConsoleAccessLevelEnum.AccessAdministrator); + + CrestronConsole.AddNewConsoleCommand(GetProviderInfo, "secretproviderinfo", + "Return data about secrets provider", ConsoleAccessLevelEnum.AccessAdministrator); } @@ -54,6 +64,79 @@ namespace PepperDash.Essentials.Core return secret; } + public static void GetProviderInfo(string cmd) + { + string response; + var args = cmd.Split(' '); + + if (cmd.Length == 0 || (args.Length == 1 && args[0] == "?")) + { + response = "Returns data about secrets provider. Format 'secretproviderinfo '"; + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + + if (args.Length == 1) + { + var provider = GetSecretProviderByKey(args[0]); + + if (provider == null) + { + response = "Invalid secrets provider key"; + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + response = String.Format("{0} : {1}", provider.Key, provider.Description); + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); + + } + + + /// + /// Console Command that returns all valid secrets in the essentials program. + /// + /// + public static void ListProviders(string cmd) + { + var response = String.Empty; + var args = cmd.Split(' '); + + if (cmd.Length == 0) + { + if (Secrets != null && Secrets.Count > 0) + { + response = Secrets.Aggregate(response, + (current, secretProvider) => current + (secretProvider.Key + "\n\r")); + } + else + { + response = "No Secrets Providers Available"; + } + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + + if (args.Length == 1 && args[0] == "?") + { + response = "Reports all valid and preset Secret providers"; + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); + + } + /// /// Add secret provider to secrets dictionary /// @@ -100,14 +183,14 @@ namespace PepperDash.Essentials.Core if (args.Length == 0) { //some Instructional Text - response = "Adds secrets to secret provider. Format 'setsecret "; + response = "Adds secrets to secret provider. Format 'setsecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } if (args.Length == 1 && args[0] == "?") { - response = "Adds secrets to secret provider. Format 'setsecret "; + response = "Adds secrets to secret provider. Format 'setsecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } @@ -134,23 +217,7 @@ namespace PepperDash.Essentials.Core var key = args[1]; var secret = args[2]; - if (provider.GetSecret(key) == null) - { - - response = provider.SetSecret(key, secret) - ? String.Format( - "Secret successfully set for {0}:{1}", - provider.Key, key) - : String.Format( - "Unable to set secret for {0}:{1}", - provider.Key, key); - CrestronConsole.ConsoleCommandResponse(response); - return; - } - response = - String.Format( - "Unable to set secret for {0}:{1} - Please use the 'UpdateSecret' command to modify it"); - CrestronConsole.ConsoleCommandResponse(response); + CrestronConsole.ConsoleCommandResponse(SetSecret(provider, key, secret)); } private static void UpdateSecretProcess(string cmd) @@ -161,7 +228,7 @@ namespace PepperDash.Essentials.Core if (args.Length == 0) { //some Instructional Text - response = "Updates secrets in secret provider. Format 'updatesecret "; + response = "Updates secrets in secret provider. Format 'updatesecret '"; CrestronConsole.ConsoleCommandResponse(response); return; @@ -169,7 +236,7 @@ namespace PepperDash.Essentials.Core if (args.Length == 1 && args[0] == "?") { - response = "Updates secrets in secret provider. Format 'updatesecret "; + response = "Updates secrets in secret provider. Format 'updatesecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } @@ -198,23 +265,49 @@ namespace PepperDash.Essentials.Core var key = args[1]; var secret = args[2]; - if (provider.GetSecret(key) != null) - { - response = provider.SetSecret(key, secret) - ? String.Format( - "Secret successfully set for {0}:{1}", - provider.Key, key) - : String.Format( - "Unable to set secret for {0}:{1}", - provider.Key, key); - CrestronConsole.ConsoleCommandResponse(response); - return; - } + CrestronConsole.ConsoleCommandResponse(UpdateSecret(provider, key, secret)); + + } + + private static string UpdateSecret(ISecretProvider provider, string key, string secret) + { + var secretPresent = provider.TestSecret(key); + + Debug.Console(2, provider, "SecretsProvider {0} {1} contain a secret entry for {2}", provider.Key, secretPresent ? "does" : "does not", key); + + if (!secretPresent) + return + String.Format( + "Unable to update secret for {0}:{1} - Please use the 'SetSecret' command to modify it"); + var response = provider.SetSecret(key, secret) + ? String.Format( + "Secret successfully set for {0}:{1}", + provider.Key, key) + : String.Format( + "Unable to set secret for {0}:{1}", + provider.Key, key); + return response; + } + + private static string SetSecret(ISecretProvider provider, string key, string secret) + { + var secretPresent = provider.TestSecret(key); + + Debug.Console(2, provider, "SecretsProvider {0} {1} contain a secret entry for {2}", provider.Key, secretPresent ? "does" : "does not", key); + + if (secretPresent) + return + String.Format( + "Unable to set secret for {0}:{1} - Please use the 'UpdateSecret' command to modify it"); + var response = provider.SetSecret(key, secret) + ? String.Format( + "Secret successfully set for {0}:{1}", + provider.Key, key) + : String.Format( + "Unable to set secret for {0}:{1}", + provider.Key, key); + return response; - response = - String.Format( - "Unable to update secret for {0}:{1} - Please use the 'SetSecret' command to create a new secret"); - CrestronConsole.ConsoleCommandResponse(response); } private static void DeleteSecretProcess(string cmd) @@ -225,14 +318,14 @@ namespace PepperDash.Essentials.Core if (args.Length == 0) { //some Instructional Text - response = "Deletes secrets in secret provider. Format 'deletesecret "; + response = "Deletes secrets in secret provider. Format 'deletesecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } if (args.Length == 1 && args[0] == "?") { - response = "Deletes secrets in secret provider. Format 'deletesecret "; + response = "Deletes secrets in secret provider. Format 'deletesecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } From 16af75ae0d841c6e84c4b8d79b13c2d9f4dfa074 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Mon, 18 Jul 2022 15:05:08 -0500 Subject: [PATCH 097/202] fix: updated erroneous console responses for Secrets Providers refactor: updated method by which the Factories assess secret objects refactor: updated 'SecretsManager' console responses feat: added 'secretproviderlist' console command feat: added 'secretproviderinfo' console command feat: added 'CrestronGlobalSecretsProvider' feat: Added 'Description' property to 'ISecretProvider' feat: added 'TestSecret' method to 'ISecretProvider' docs: added xml comments to 'ISecretProvider' docs: added xml comments to 'ISecret' refactor: cleaned up crestron default secrets provider classes refactor: moved 'CrestronSecret' to its own class file refactor: overhauled all secrets-related console commands resolves #968 --- .../PepperDash_Essentials_Core.csproj | 4 +- .../Secrets/CrestronGlobalSecretsProvider.cs | 102 +++++++++ ...der.cs => CrestronLocalSecretsProvider.cs} | 199 +++++++++--------- .../Secrets/CrestronSecret.cs | 28 +++ .../Secrets/Interfaces.cs | 34 +++ .../Secrets/SecretsManager.cs | 181 ++++++++++++---- 6 files changed, 406 insertions(+), 142 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronGlobalSecretsProvider.cs rename essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/{CrestronSecretsProvider.cs => CrestronLocalSecretsProvider.cs} (65%) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecret.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index c0903526..252a881e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -338,7 +338,9 @@ - + + + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronGlobalSecretsProvider.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronGlobalSecretsProvider.cs new file mode 100644 index 00000000..5adefd9e --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronGlobalSecretsProvider.cs @@ -0,0 +1,102 @@ +using System; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronDataStore; +using PepperDash.Core; + + +namespace PepperDash.Essentials.Core +{ + public class CrestronGlobalSecretsProvider : ISecretProvider + { + public string Key { get; set; } + //Added for reference + public string Description { get; private set; } + + public CrestronGlobalSecretsProvider(string key) + { + Key = key; + Description = String.Format("Default secret provider serving all local applications"); + + } + + static CrestronGlobalSecretsProvider() + { + //Added for future encrypted reference + var secureSupported = CrestronSecureStorage.Supported; + + CrestronDataStoreStatic.InitCrestronDataStore(); + if (secureSupported) + { + //doThingsFuture + } + } + + /// + /// Set secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// Secret Value + public bool SetSecret(string key, object value) + { + var secret = value as string; + CrestronDataStore.CDS_ERROR returnCode; + + if (String.IsNullOrEmpty(secret)) + { + returnCode = CrestronDataStoreStatic.clearGlobal(key); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + { + Debug.Console(0, this, "Successfully removed secret \"{0}\"", secret); + return true; + } + } + + else + { + returnCode = CrestronDataStoreStatic.SetGlobalStringValue(key, secret); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + { + Debug.Console(0, this, "Successfully set secret \"{0}\"", secret); + return true; + } + } + + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString()); + return false; + } + + /// + /// Retrieve secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// ISecret Object containing key, provider, and value + public ISecret GetSecret(string key) + { + string mySecret; + var getErrorCode = CrestronDataStoreStatic.GetGlobalStringValue(key, out mySecret); + + switch (getErrorCode) + { + case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: + Debug.Console(2, this, "Secret Successfully retrieved for {0}:{1}", Key, key); + return new CrestronSecret(key, mySecret, this); + default: + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}", + Key, key, getErrorCode.ToString()); + return null; + } + } + + /// + /// Determine if a secret is present within the provider without retrieving it + /// + /// Secret Key + /// bool if present + public bool TestSecret(string key) + { + string mySecret; + return CrestronDataStoreStatic.GetGlobalStringValue(key, out mySecret) == CrestronDataStore.CDS_ERROR.CDS_SUCCESS; + } + } + +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronLocalSecretsProvider.cs similarity index 65% rename from essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs rename to essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronLocalSecretsProvider.cs index 0c531a08..955c875c 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronLocalSecretsProvider.cs @@ -1,98 +1,103 @@ -using System; -using Crestron.SimplSharp; -using Crestron.SimplSharp.CrestronDataStore; -using PepperDash.Core; - - -namespace PepperDash.Essentials.Core -{ - public class CrestronSecretsProvider : ISecretProvider - { - public string Key { get; set; } - //Added for reference - private static readonly bool SecureSupported; - public CrestronSecretsProvider(string key) - { - Key = key; - } - - static CrestronSecretsProvider() - { - //Added for future encrypted reference - SecureSupported = CrestronSecureStorage.Supported; - - CrestronDataStoreStatic.InitCrestronDataStore(); - if (SecureSupported) - { - //doThingsFuture - } - } - - /// - /// Set secret for item in the CrestronSecretsProvider - /// - /// Secret Key - /// Secret Value - public bool SetSecret(string key, object value) - { - var secret = value as string; - CrestronDataStore.CDS_ERROR returnCode; - - if (String.IsNullOrEmpty(secret)) - { - returnCode = CrestronDataStoreStatic.clearLocal(key); - if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) return true; - } - - else - { - returnCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret); - if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) return true; - } - - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString()); - return false; - } - - /// - /// Retrieve secret for item in the CrestronSecretsProvider - /// - /// Secret Key - /// ISecret Object containing key, provider, and value - public ISecret GetSecret(string key) - { - string mySecret; - var getErrorCode = CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret); - - switch (getErrorCode) - { - case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: - Debug.Console(2, this, "Secret Successfully retrieved for {0}:{1}", Key, key); - return new CrestronSecret(key, mySecret, this); - default: - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}", - Key, key, getErrorCode.ToString()); - return null; - } - } - } - - /// - /// Special container class for CrestronSecret provider - /// - public class CrestronSecret : ISecret - { - public ISecretProvider Provider { get; private set; } - public string Key { get; private set; } - - public object Value { get; private set; } - - public CrestronSecret(string key, string value, ISecretProvider provider) - { - Key = key; - Value = value; - Provider = provider; - } - - } +using System; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronDataStore; +using PepperDash.Core; +using Crestron.SimplSharpPro; + + +namespace PepperDash.Essentials.Core +{ + public class CrestronLocalSecretsProvider : ISecretProvider + { + public string Key { get; set; } + //Added for reference + public string Description { get; private set; } + + + public CrestronLocalSecretsProvider(string key) + { + Key = key; + Description = String.Format("Default secret provider serving Essentials Application {0}", InitialParametersClass.ApplicationNumber); + } + + static CrestronLocalSecretsProvider() + { + //Added for future encrypted reference + var secureSupported = CrestronSecureStorage.Supported; + + CrestronDataStoreStatic.InitCrestronDataStore(); + if (secureSupported) + { + //doThingsFuture + } + } + + /// + /// Set secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// Secret Value + public bool SetSecret(string key, object value) + { + var secret = value as string; + CrestronDataStore.CDS_ERROR returnCode; + + if (String.IsNullOrEmpty(secret)) + { + returnCode = CrestronDataStoreStatic.clearLocal(key); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + { + Debug.Console(0, this, "Successfully removed secret \"{0}\"", secret); + return true; + } + } + + else + { + returnCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + { + Debug.Console(0, this, "Successfully set secret \"{0}\"", secret); + return true; + } + } + + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString()); + return false; + } + + /// + /// Retrieve secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// ISecret Object containing key, provider, and value + public ISecret GetSecret(string key) + { + string mySecret; + var getErrorCode = CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret); + + switch (getErrorCode) + { + case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: + Debug.Console(2, this, "Secret Successfully retrieved for {0}:{1}", Key, key); + return new CrestronSecret(key, mySecret, this); + default: + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}", + Key, key, getErrorCode.ToString()); + return null; + } + } + + /// + /// Determine if a secret is present within the provider without retrieving it + /// + /// Secret Key + /// bool if present + public bool TestSecret(string key) + { + string mySecret; + return CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret) == CrestronDataStore.CDS_ERROR.CDS_SUCCESS; + } + } + } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecret.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecret.cs new file mode 100644 index 00000000..27fbcdad --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecret.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Essentials.Core +{ + /// + /// Special container class for CrestronSecret provider + /// + public class CrestronSecret : ISecret + { + public ISecretProvider Provider { get; private set; } + public string Key { get; private set; } + + public object Value { get; private set; } + + public CrestronSecret(string key, string value, ISecretProvider provider) + { + Key = key; + Value = value; + Provider = provider; + } + + } + +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs index 43c6a230..e61ac208 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs @@ -7,9 +7,32 @@ namespace PepperDash.Essentials.Core /// public interface ISecretProvider : IKeyed { + /// + /// Set secret value for provider by key + /// + /// key of secret to set + /// value to set secret to + /// bool SetSecret(string key, object value); + /// + /// Return object containing secret from provider + /// + /// key of secret to retrieve + /// ISecret GetSecret(string key); + + /// + /// Verifies presence of secret + /// + /// key of secret to chek + /// + bool TestSecret(string key); + + /// + /// Description of the secrets provider + /// + string Description { get; } } /// @@ -17,8 +40,19 @@ namespace PepperDash.Essentials.Core /// public interface ISecret { + /// + /// Instance of ISecretProvider that the secret belongs to + /// ISecretProvider Provider { get; } + + /// + /// Key of the secret in the provider + /// string Key { get; } + + /// + /// Value of the secret + /// object Value { get; } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs index bcb46ff5..95a94a24 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; using Crestron.SimplSharp; using PepperDash.Core; - namespace PepperDash.Essentials.Core { public static class SecretsManager @@ -16,18 +16,28 @@ namespace PepperDash.Essentials.Core public static void Initialize() { - AddSecretProvider("default", new CrestronSecretsProvider("default")); + AddSecretProvider("default", new CrestronLocalSecretsProvider("default")); + + AddSecretProvider("CrestronGlobalSecrets", new CrestronGlobalSecretsProvider("CrestronGlobalSecrets")); CrestronConsole.AddNewConsoleCommand(SetSecretProcess, "setsecret", - "Adds secrets to secret provider", + "Adds secret to secrets provider", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(UpdateSecretProcess, "updatesecret", - "Updates secrets in secret provider", + "Updates secret in secrets provider", ConsoleAccessLevelEnum.AccessAdministrator); CrestronConsole.AddNewConsoleCommand(DeleteSecretProcess, "deletesecret", - "Deletes secrets in secret provider", + "Deletes secret from secrest provider", + ConsoleAccessLevelEnum.AccessAdministrator); + + CrestronConsole.AddNewConsoleCommand(ListProviders, "secretproviderlist", + "Return list of all valid secrets providers", + ConsoleAccessLevelEnum.AccessAdministrator); + + CrestronConsole.AddNewConsoleCommand(GetProviderInfo, "secretproviderinfo", + "Return data about secrets provider", ConsoleAccessLevelEnum.AccessAdministrator); } @@ -54,6 +64,79 @@ namespace PepperDash.Essentials.Core return secret; } + public static void GetProviderInfo(string cmd) + { + string response; + var args = cmd.Split(' '); + + if (cmd.Length == 0 || (args.Length == 1 && args[0] == "?")) + { + response = "Returns data about secrets provider. Format 'secretproviderinfo '"; + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + + if (args.Length == 1) + { + var provider = GetSecretProviderByKey(args[0]); + + if (provider == null) + { + response = "Invalid secrets provider key"; + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + response = String.Format("{0} : {1}", provider.Key, provider.Description); + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); + + } + + + /// + /// Console Command that returns all valid secrets in the essentials program. + /// + /// + public static void ListProviders(string cmd) + { + var response = String.Empty; + var args = cmd.Split(' '); + + if (cmd.Length == 0) + { + if (Secrets != null && Secrets.Count > 0) + { + response = Secrets.Aggregate(response, + (current, secretProvider) => current + (secretProvider.Key + "\n\r")); + } + else + { + response = "No Secrets Providers Available"; + } + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + + if (args.Length == 1 && args[0] == "?") + { + response = "Reports all valid and preset Secret providers"; + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); + + } + /// /// Add secret provider to secrets dictionary /// @@ -100,14 +183,14 @@ namespace PepperDash.Essentials.Core if (args.Length == 0) { //some Instructional Text - response = "Adds secrets to secret provider. Format 'setsecret "; + response = "Adds secrets to secret provider. Format 'setsecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } if (args.Length == 1 && args[0] == "?") { - response = "Adds secrets to secret provider. Format 'setsecret "; + response = "Adds secrets to secret provider. Format 'setsecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } @@ -134,23 +217,7 @@ namespace PepperDash.Essentials.Core var key = args[1]; var secret = args[2]; - if (provider.GetSecret(key) == null) - { - - response = provider.SetSecret(key, secret) - ? String.Format( - "Secret successfully set for {0}:{1}", - provider.Key, key) - : String.Format( - "Unable to set secret for {0}:{1}", - provider.Key, key); - CrestronConsole.ConsoleCommandResponse(response); - return; - } - response = - String.Format( - "Unable to set secret for {0}:{1} - Please use the 'UpdateSecret' command to modify it"); - CrestronConsole.ConsoleCommandResponse(response); + CrestronConsole.ConsoleCommandResponse(SetSecret(provider, key, secret)); } private static void UpdateSecretProcess(string cmd) @@ -161,7 +228,7 @@ namespace PepperDash.Essentials.Core if (args.Length == 0) { //some Instructional Text - response = "Updates secrets in secret provider. Format 'updatesecret "; + response = "Updates secrets in secret provider. Format 'updatesecret '"; CrestronConsole.ConsoleCommandResponse(response); return; @@ -169,7 +236,7 @@ namespace PepperDash.Essentials.Core if (args.Length == 1 && args[0] == "?") { - response = "Updates secrets in secret provider. Format 'updatesecret "; + response = "Updates secrets in secret provider. Format 'updatesecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } @@ -198,23 +265,49 @@ namespace PepperDash.Essentials.Core var key = args[1]; var secret = args[2]; - if (provider.GetSecret(key) != null) - { - response = provider.SetSecret(key, secret) - ? String.Format( - "Secret successfully set for {0}:{1}", - provider.Key, key) - : String.Format( - "Unable to set secret for {0}:{1}", - provider.Key, key); - CrestronConsole.ConsoleCommandResponse(response); - return; - } + CrestronConsole.ConsoleCommandResponse(UpdateSecret(provider, key, secret)); + + } + + private static string UpdateSecret(ISecretProvider provider, string key, string secret) + { + var secretPresent = provider.TestSecret(key); + + Debug.Console(2, provider, "SecretsProvider {0} {1} contain a secret entry for {2}", provider.Key, secretPresent ? "does" : "does not", key); + + if (!secretPresent) + return + String.Format( + "Unable to update secret for {0}:{1} - Please use the 'SetSecret' command to modify it"); + var response = provider.SetSecret(key, secret) + ? String.Format( + "Secret successfully set for {0}:{1}", + provider.Key, key) + : String.Format( + "Unable to set secret for {0}:{1}", + provider.Key, key); + return response; + } + + private static string SetSecret(ISecretProvider provider, string key, string secret) + { + var secretPresent = provider.TestSecret(key); + + Debug.Console(2, provider, "SecretsProvider {0} {1} contain a secret entry for {2}", provider.Key, secretPresent ? "does" : "does not", key); + + if (secretPresent) + return + String.Format( + "Unable to set secret for {0}:{1} - Please use the 'UpdateSecret' command to modify it"); + var response = provider.SetSecret(key, secret) + ? String.Format( + "Secret successfully set for {0}:{1}", + provider.Key, key) + : String.Format( + "Unable to set secret for {0}:{1}", + provider.Key, key); + return response; - response = - String.Format( - "Unable to update secret for {0}:{1} - Please use the 'SetSecret' command to create a new secret"); - CrestronConsole.ConsoleCommandResponse(response); } private static void DeleteSecretProcess(string cmd) @@ -225,14 +318,14 @@ namespace PepperDash.Essentials.Core if (args.Length == 0) { //some Instructional Text - response = "Deletes secrets in secret provider. Format 'deletesecret "; + response = "Deletes secrets in secret provider. Format 'deletesecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } if (args.Length == 1 && args[0] == "?") { - response = "Deletes secrets in secret provider. Format 'deletesecret "; + response = "Deletes secrets in secret provider. Format 'deletesecret '"; CrestronConsole.ConsoleCommandResponse(response); return; } From afd2198eef99746e237a514ee8cdd3303328718b Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 1 Aug 2022 12:19:28 -0600 Subject: [PATCH 098/202] Uses a less specific interface type for routing --- PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index ba4567dc..5ef76e1a 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -712,7 +712,8 @@ namespace PepperDash.Essentials else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) dest = DefaultDisplay; else - dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching; + dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink; + if (dest == null) { From 5b350c7a0cfcd508d5f76c69535de59dbc7ad0e3 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 1 Aug 2022 12:19:43 -0600 Subject: [PATCH 099/202] Updates interface type for other condition --- PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index 5ef76e1a..e622983f 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -708,7 +708,7 @@ namespace PepperDash.Essentials IRoutingSink dest = null; if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase)) - dest = DefaultAudioDevice as IRoutingSinkNoSwitching; + dest = DefaultAudioDevice as IRoutingSink; else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) dest = DefaultDisplay; else From 008c82edb9fe4bd8555049790a5532bdcfa25063 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Mon, 8 Aug 2022 13:54:17 -0500 Subject: [PATCH 100/202] fix: updated lighting and display base; fix: lightingBase scene recall link to api index out of range exception --- .../Display/DisplayBase.cs | 261 +++++++++--------- .../Lighting/LightingBase.cs | 87 ++++-- 2 files changed, 190 insertions(+), 158 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/DisplayBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/DisplayBase.cs index 17ff8bd1..d374099f 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/DisplayBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/DisplayBase.cs @@ -105,9 +105,6 @@ namespace PepperDash.Essentials.Core protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { - var inputNumber = 0; - var inputKeys = new List(); - var joinMap = new DisplayControllerJoinMap(joinStart); var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); @@ -124,133 +121,141 @@ namespace PepperDash.Essentials.Core Debug.Console(0,this,"Please update config to use 'eiscapiadvanced' to get all join map features for this device."); } - Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - Debug.Console(0, "Linking to Display: {0}", displayDevice.Name); - - trilist.StringInput[joinMap.Name.JoinNumber].StringValue = displayDevice.Name; - - var commMonitor = displayDevice as ICommunicationMonitor; - if (commMonitor != null) - { - commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); - } - - var inputNumberFeedback = new IntFeedback(() => inputNumber); - - // Two way feedbacks - var twoWayDisplay = displayDevice as TwoWayDisplayBase; - - if (twoWayDisplay != null) - { - trilist.SetBool(joinMap.IsTwoWayDisplay.JoinNumber, true); - - twoWayDisplay.CurrentInputFeedback.OutputChange += (o, a) => Debug.Console(0, "CurrentInputFeedback_OutputChange {0}", a.StringValue); - - - inputNumberFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputSelect.JoinNumber]); - } - - // Power Off - trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () => - { - inputNumber = 102; - inputNumberFeedback.FireUpdate(); - displayDevice.PowerOff(); - }); - - var twoWayDisplayDevice = displayDevice as TwoWayDisplayBase; - if (twoWayDisplayDevice != null) - { - twoWayDisplayDevice.PowerIsOnFeedback.OutputChange += (o, a) => - { - if (!a.BoolValue) - { - inputNumber = 102; - inputNumberFeedback.FireUpdate(); - - } - else - { - inputNumber = 0; - inputNumberFeedback.FireUpdate(); - } - }; - - twoWayDisplayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]); - twoWayDisplayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]); - } - - // PowerOn - trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () => - { - inputNumber = 0; - inputNumberFeedback.FireUpdate(); - displayDevice.PowerOn(); - }); - - - - for (int i = 0; i < displayDevice.InputPorts.Count; i++) - { - if (i < joinMap.InputNamesOffset.JoinSpan) - { - inputKeys.Add(displayDevice.InputPorts[i].Key); - var tempKey = inputKeys.ElementAt(i); - trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset.JoinNumber + i), - () => displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector)); - Debug.Console(2, displayDevice, "Setting Input Select Action on Digital Join {0} to Input: {1}", - joinMap.InputSelectOffset.JoinNumber + i, displayDevice.InputPorts[tempKey].Key.ToString()); - trilist.StringInput[(ushort)(joinMap.InputNamesOffset.JoinNumber + i)].StringValue = displayDevice.InputPorts[i].Key.ToString(); - } - else - Debug.Console(0, displayDevice, Debug.ErrorLogLevel.Warning, "Device has {0} inputs. The Join Map allows up to {1} inputs. Discarding inputs {2} - {3} from bridge.", - displayDevice.InputPorts.Count, joinMap.InputNamesOffset.JoinSpan, i + 1, displayDevice.InputPorts.Count); - } - - Debug.Console(2, displayDevice, "Setting Input Select Action on Analog Join {0}", joinMap.InputSelect); - trilist.SetUShortSigAction(joinMap.InputSelect.JoinNumber, (a) => - { - if (a == 0) - { - displayDevice.PowerOff(); - inputNumber = 0; - } - else if (a > 0 && a < displayDevice.InputPorts.Count && a != inputNumber) - { - displayDevice.ExecuteSwitch(displayDevice.InputPorts.ElementAt(a - 1).Selector); - inputNumber = a; - } - else if (a == 102) - { - displayDevice.PowerToggle(); - - } - if (twoWayDisplay != null) - inputNumberFeedback.FireUpdate(); - }); - - - var volumeDisplay = displayDevice as IBasicVolumeControls; - if (volumeDisplay == null) return; - - trilist.SetBoolSigAction(joinMap.VolumeUp.JoinNumber, volumeDisplay.VolumeUp); - trilist.SetBoolSigAction(joinMap.VolumeDown.JoinNumber, volumeDisplay.VolumeDown); - trilist.SetSigTrueAction(joinMap.VolumeMute.JoinNumber, volumeDisplay.MuteToggle); - - var volumeDisplayWithFeedback = volumeDisplay as IBasicVolumeWithFeedback; - - if (volumeDisplayWithFeedback == null) return; - trilist.SetSigTrueAction(joinMap.VolumeMuteOn.JoinNumber, volumeDisplayWithFeedback.MuteOn); - trilist.SetSigTrueAction(joinMap.VolumeMuteOff.JoinNumber, volumeDisplayWithFeedback.MuteOff); - - - trilist.SetUShortSigAction(joinMap.VolumeLevel.JoinNumber, volumeDisplayWithFeedback.SetVolume); - volumeDisplayWithFeedback.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[joinMap.VolumeLevel.JoinNumber]); - volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMute.JoinNumber]); - volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMuteOn.JoinNumber]); - volumeDisplayWithFeedback.MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.VolumeMuteOff.JoinNumber]); + LinkDisplayToApi(displayDevice, trilist, joinMap); } + protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, DisplayControllerJoinMap joinMap) + { + Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + Debug.Console(0, "Linking to Display: {0}", displayDevice.Name); + + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = displayDevice.Name; + + var commMonitor = displayDevice as ICommunicationMonitor; + if (commMonitor != null) + { + commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + } + + var inputNumber = 0; + var inputKeys = new List(); + + 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]); + } + } /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Lighting/LightingBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Lighting/LightingBase.cs index 569d2005..604965af 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Lighting/LightingBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Lighting/LightingBase.cs @@ -70,44 +70,71 @@ namespace PepperDash.Essentials.Core.Lighting } } - protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart, - string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new GenericLightingJoinMap(joinStart); + protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart, + string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new GenericLightingJoinMap(joinStart); - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } - Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + return LinkLightingToApi(lightingDevice, trilist, joinMap); + } - Debug.Console(0, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString()); + protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap) + { - // GenericLighitng Actions & FeedBack - trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u])); - var sceneIndex = 0; - foreach (var scene in lightingDevice.LightingScenes) - { - trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[sceneIndex])); - scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex)]); - trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex)].StringValue = scene.Name; - trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + sceneIndex)].BoolValue = true; - sceneIndex++; - } + Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - return joinMap; - } + Debug.Console(0, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString()); + + // GenericLighitng Actions & FeedBack + trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u])); + + var sceneIndex = 0; + foreach (var scene in lightingDevice.LightingScenes) + { + var index = sceneIndex; + + trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + index), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[index])); + scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)]); + trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name; + trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true; + + sceneIndex++; + } + + trilist.OnlineStatusChange += (sender, args) => + { + if (!args.DeviceOnLine) return; + + sceneIndex = 0; + foreach (var scene in lightingDevice.LightingScenes) + { + var index = sceneIndex; + + trilist.StringInput[(uint) (joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name; + trilist.BooleanInput[(uint) (joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true; + scene.IsActiveFeedback.FireUpdate(); + + sceneIndex++; + } + }; + + return joinMap; + } } From 49e44ec85047faa90b75a26285ef32a114339a72 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 10 Aug 2022 15:49:41 -0500 Subject: [PATCH 101/202] fix: updated VideoCodecBase UpdateDirectoryXSig to handle directory results that are greater than 1023, XSig maximimum index --- .../VideoCodec/VideoCodecBase.cs | 30 ++++++++++++------- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 5 ++-- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 593472e9..d07d5f81 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1180,31 +1180,39 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot) { - var contactIndex = 1; - var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count]; + var xSigMaxIndex = 1023; + var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count > xSigMaxIndex + ? xSigMaxIndex + : directory.CurrentDirectoryResults.Count]; - 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 counterIndex = 1; + foreach (var entry in contacts) { - 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}", entry.Name, entry.FolderId, entryIndex); if (entry is DirectoryFolder && entry.ParentFolderId == "root") { - tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, String.Format("[+] {0}", entry.Name)); + tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, String.Format("[+] {0}", entry.Name)); - contactIndex++; + counterIndex++; continue; } - tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, entry.Name); + tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, entry.Name); - contactIndex++; + counterIndex++; } - + return GetXSigString(tokenArray); } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 73c1e8c5..6ba1082f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2730,6 +2730,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Debug.Console(2, this, "OnDirectoryResultReturned. Result has {0} contacts", result.Contacts.Count); 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 (!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue) @@ -2747,7 +2748,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom //} Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0} Contact Count: {1}", - !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue, directoryResult.Contacts.Count); + directoryIsRoot, directoryResult.Contacts.Count); // This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology var handler = DirectoryResultReturned; @@ -2756,7 +2757,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom handler(this, new DirectoryEventArgs { Directory = directoryResult, - DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue + DirectoryIsOnRoot = directoryIsRoot }); } From c446c3a976e9719190921ec2e8cb6e731a3100dd Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 10 Aug 2022 17:12:30 -0500 Subject: [PATCH 102/202] fix: updates to resolve directory display issues on touch panel when bridged --- .../VideoCodec/VideoCodecBase.cs | 19 ++++++++++++------- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 4 +++- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index d07d5f81..6e577c59 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp.CrestronIO; +using Crestron.SimplSharp.Reflection; using Crestron.SimplSharp.Ssh; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharp; @@ -1010,7 +1011,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetString(joinMap.DirectoryEntries.JoinNumber, 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); @@ -1025,7 +1026,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetString(joinMap.DirectoryEntries.JoinNumber, Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var directoryXSig = UpdateDirectoryXSig(args.Directory, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); + var directoryXSig = UpdateDirectoryXSig(args.Directory, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length); @@ -1036,10 +1037,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (!args.DeviceOnLine) return; - // TODO [ ] Issue #868 trilist.SetString(joinMap.DirectoryEntries.JoinNumber, "\xFC"); UpdateDirectoryXSig(codec.CurrentDirectoryResult, - !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); + codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); }; } @@ -1190,16 +1190,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec 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 contacts) + foreach (var entry in contactsToDisplay) { var arrayIndex = counterIndex - 1; var entryIndex = counterIndex; - Debug.Console(2, this, "Entry{2:0000} Name: {0}, Folder ID: {1}", entry.Name, entry.FolderId, entryIndex); + 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(entryIndex, String.Format("[+] {0}", entry.Name)); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 6ba1082f..32415d1d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2729,6 +2729,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { Debug.Console(2, this, "OnDirectoryResultReturned. Result has {0} contacts", result.Contacts.Count); + CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); + var directoryResult = result; var directoryIsRoot = CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false; @@ -2761,7 +2763,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom }); } - CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); + } catch (Exception e) { From ed335cc9aeea8a81e939b31d111ac1fa7ea8df44 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Fri, 12 Aug 2022 09:26:09 -0400 Subject: [PATCH 103/202] Fixes for offline feedback for DM endpoints that don't provide offline feedback in the hardware definition. Adds offline and name feedback to joinMap for these devices. --- .../Crestron/CrestronGenericBaseDevice.cs | 2 +- .../Receivers/DmHdBaseTEndpointController.cs | 30 ++++++++++- .../Receivers/DmRmc4k100C1GController.cs | 34 ++++++++++-- .../Endpoints/Receivers/DmRmcHelper.cs | 30 +++++------ .../Transmitters/DmTx4k100Controller.cs | 34 ++++++++---- .../Endpoints/Transmitters/DmTxHelpers.cs | 54 ++++++++++--------- .../Transmitters/HDBaseTTxController.cs | 24 ++++++++- 7 files changed, 149 insertions(+), 59 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs index f4d13d4e..32407ba3 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs @@ -20,7 +20,7 @@ namespace PepperDash.Essentials.Core /// public FeedbackCollection Feedbacks { get; private set; } - public BoolFeedback IsOnline { get; set; } + public BoolFeedback IsOnline { get; private set; } public BoolFeedback IsRegistered { get; private set; } public StringFeedback IpConnectionsText { get; private set; } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmHdBaseTEndpointController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmHdBaseTEndpointController.cs index 3af4f0fe..ec3553a1 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmHdBaseTEndpointController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmHdBaseTEndpointController.cs @@ -1,8 +1,10 @@ -using Crestron.SimplSharp.Ssh; +using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DM.Endpoints.Receivers; - +using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core; +using PepperDash.Core; +using Newtonsoft.Json; namespace PepperDash.Essentials.DM { @@ -28,6 +30,30 @@ namespace PepperDash.Essentials.DM OutputPorts = new RoutingPortCollection {HDBaseTSink}; } + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new DmRmcControllerJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } + + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = this.Name; + } + #region IComPorts Members public CrestronCollection ComPorts { get { return Rmc.ComPorts; } } public int NumberOfComPorts { get { return Rmc.NumberOfComPorts; } } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4k100C1GController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4k100C1GController.cs index 92af7ce1..529f740a 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4k100C1GController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4k100C1GController.cs @@ -1,9 +1,11 @@ using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DM; -using Crestron.SimplSharpPro.DM.Endpoints.Receivers; - -using PepperDash.Essentials.Core; - +using Crestron.SimplSharpPro.DM.Endpoints.Receivers; +using Crestron.SimplSharpPro.DeviceSupport; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core; +using PepperDash.Core; +using Newtonsoft.Json; namespace PepperDash.Essentials.DM { @@ -31,6 +33,30 @@ namespace PepperDash.Essentials.DM InputPorts = new RoutingPortCollection {DmIn}; OutputPorts = new RoutingPortCollection {HdmiOut}; + } + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new DmRmcControllerJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } + + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = this.Name; } #region IIROutputPorts Members diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs index ced21918..5d644a2a 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs @@ -188,7 +188,7 @@ namespace PepperDash.Essentials.DM #endregion } - public abstract class DmHdBaseTControllerBase : CrestronGenericBaseDevice + public abstract class DmHdBaseTControllerBase : CrestronGenericBridgeableBaseDevice { protected HDBaseTBase Rmc; @@ -342,12 +342,12 @@ namespace PepperDash.Essentials.DM return null; } // Must use different constructor for DMPS4K types. No IPID - if (Global.ControlSystemIsDmps4kType) + if (Global.ControlSystemIsDmps4kType || typeName == "hdbasetrx" || typeName == "dmrmc4k100c1g") { var rmc = GetDmRmcControllerForDmps4k(key, name, typeName, dmps, props.ParentOutputNumber); Debug.Console(0, "DM endpoint output {0} is for Dmps4k, changing online feedback to chassis", num); - rmc.IsOnline = dmps.OutputEndpointOnlineFeedbacks[num]; - rmc.IsOnline.OutputChange += (currentDevice, args) => + rmc.IsOnline.SetValueFunc(() => dmps.OutputEndpointOnlineFeedbacks[num].BoolValue); + dmps.OutputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => { foreach (var feedback in rmc.Feedbacks) { @@ -380,19 +380,20 @@ namespace PepperDash.Essentials.DM if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || - chassis is DmMd128x128 || chassis is DmMd64x64) + chassis is DmMd128x128 || chassis is DmMd64x64 + || typeName == "hdbasetrx" || typeName == "dmrmc4k100c1g") { var rmc = GetDmRmcControllerForCpu3Chassis(key, name, typeName, chassis, num, parentDev); Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); - rmc.IsOnline = controller.OutputEndpointOnlineFeedbacks[num]; - rmc.IsOnline.OutputChange += (currentDevice, args) => - { - foreach (var feedback in rmc.Feedbacks) + rmc.IsOnline.SetValueFunc(() => controller.OutputEndpointOnlineFeedbacks[num].BoolValue); + controller.OutputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => { - if (feedback != null) - feedback.FireUpdate(); - } - }; + foreach (var feedback in rmc.Feedbacks) + { + if (feedback != null) + feedback.FireUpdate(); + } + }; return rmc; } return GetDmRmcControllerForCpu2Chassis(key, name, typeName, ipid, chassis, num, parentDev); @@ -521,8 +522,7 @@ namespace PepperDash.Essentials.DM var props = JsonConvert.DeserializeObject (dc.Properties.ToString()); - return DmRmcHelper.GetDmRmcController(dc.Key, dc.Name, type, props); - + return DmRmcHelper.GetDmRmcController(dc.Key, dc.Name, type, props); } } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k100Controller.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k100Controller.cs index d2a9f7bc..5bbf5fd5 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k100Controller.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k100Controller.cs @@ -6,6 +6,7 @@ using Crestron.SimplSharpPro.DM.Endpoints.Transmitters; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; +using Newtonsoft.Json; namespace PepperDash.Essentials.DM { @@ -20,14 +21,6 @@ namespace PepperDash.Essentials.DM public RoutingInputPort HdmiIn { get; private set; } public RoutingOutputPort DmOut { get; private set; } - //public IntFeedback VideoSourceNumericFeedback { get; protected set; } - //public IntFeedback AudioSourceNumericFeedback { get; protected set; } - //public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; } - //public IntFeedback HdmiIn2HdcpCapabilityFeedback { get; protected set; } - - //public override IntFeedback HdcpSupportAllFeedback { get; protected set; } - //public override ushort HdcpSupportCapability { get; protected set; } - /// /// Helps get the "real" inputs, including when in Auto /// @@ -70,11 +63,34 @@ namespace PepperDash.Essentials.DM HdmiIn.Port = Tx; PreventRegistration = true; + + var parentDev = DeviceManager.GetDeviceForKey(key); + var num = tx.DMInputOutput.Number; + if (parentDev is DmpsRoutingController) + { + var dmps = parentDev as DmpsRoutingController; + IsOnline.SetValueFunc(() => dmps.InputEndpointOnlineFeedbacks[num].BoolValue); + dmps.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); + } + else if (parentDev is DmChassisController) + { + var controller = parentDev as DmChassisController; + IsOnline.SetValueFunc(() => controller.InputEndpointOnlineFeedbacks[num].BoolValue); + controller.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); + } } public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { - Debug.Console(1, this, "No properties to link. Skipping device {0}", Name); + var joinMap = new HDBaseTTxControllerJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + this.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = this.Name; } #region IIROutputPorts Members diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs index 4883849e..d04f462c 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs @@ -221,37 +221,39 @@ namespace PepperDash.Essentials.DM protected DmTxControllerBase(string key, string name, EndpointTransmitterBase hardware) : base(key, name, hardware) { - // if wired to a chassis or DMPS, skip registration step in base class - if (hardware.DMInput != null || (Global.ControlSystemIsDmpsType && hardware.DMInput != null)) - { - this.PreventRegistration = true; - } - AddToFeedbackList(ActiveVideoInputFeedback); - var parentDev = DeviceManager.GetDeviceForKey(key); - var num = hardware.DMInput.Number; - - //If Dmps4K, change online feedback to chassis, tx feedback does not work - if (parentDev is DmpsRoutingController && Global.ControlSystemIsDmps4kType) + // if wired to a chassis or DMPS, skip registration step in base class + if (hardware.DMInput != null) { - var dmps = parentDev as DmpsRoutingController; - Debug.Console(0, "DM endpoint input {0} is for Dmps4k, changing online feedback to chassis", num); - IsOnline = dmps.InputEndpointOnlineFeedbacks[num]; - } - //If Cpu3 Chassis, change online feedback to chassis, tx feedback does not work - else if (parentDev is DmChassisController) - { - var controller = parentDev as DmChassisController; - var chassis = controller.Chassis; + this.PreventRegistration = true; - if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || - chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || - chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || - chassis is DmMd128x128 || chassis is DmMd64x64) + var parentDev = DeviceManager.GetDeviceForKey(key); + var num = hardware.DMInput.Number; + + //If Dmps4K, change online feedback to chassis, tx feedback does not work + if (parentDev is DmpsRoutingController && Global.ControlSystemIsDmps4kType) { - Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); - IsOnline = controller.InputEndpointOnlineFeedbacks[num]; + var dmps = parentDev as DmpsRoutingController; + Debug.Console(0, "DM endpoint input {0} is for Dmps4k, changing online feedback to chassis", num); + IsOnline.SetValueFunc(() => dmps.InputEndpointOnlineFeedbacks[num].BoolValue); + dmps.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); + } + //If Cpu3 Chassis, change online feedback to chassis, tx feedback does not work + else if (parentDev is DmChassisController) + { + var controller = parentDev as DmChassisController; + var chassis = controller.Chassis; + + if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || + chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || + chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || + chassis is DmMd128x128 || chassis is DmMd64x64) + { + Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); + IsOnline.SetValueFunc(() => controller.InputEndpointOnlineFeedbacks[num].BoolValue); + controller.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); + } } } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs index 800da2a9..d7a78237 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs @@ -6,6 +6,7 @@ using Crestron.SimplSharp; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DM.Endpoints.Transmitters; +using Crestron.SimplSharpPro.DM; using Newtonsoft.Json; using PepperDash.Core; @@ -18,7 +19,7 @@ namespace PepperDash.Essentials.DM /// Controller class for suitable for HDBaseT transmitters /// [Description("Wrapper Class for HDBaseT devices based on HDTx3CB class")] - public class HDBaseTTxController: BasicDmTxControllerBase, IRoutingInputsOutputs, IComPorts + public class HDBaseTTxController : BasicDmTxControllerBase, IRoutingInputsOutputs, IComPorts { public RoutingInputPort HdmiIn { get; private set; } public RoutingOutputPort DmOut { get; private set; } @@ -34,6 +35,21 @@ namespace PepperDash.Essentials.DM InputPorts = new RoutingPortCollection { HdmiIn }; OutputPorts = new RoutingPortCollection { DmOut }; + + var parentDev = DeviceManager.GetDeviceForKey(key); + var num = tx.DMInputOutput.Number; + if (parentDev is DmpsRoutingController) + { + var dmps = parentDev as DmpsRoutingController; + IsOnline.SetValueFunc(() => dmps.InputEndpointOnlineFeedbacks[num].BoolValue); + dmps.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); + } + else if (parentDev is DmChassisController) + { + var controller = parentDev as DmChassisController; + IsOnline.SetValueFunc(() => controller.InputEndpointOnlineFeedbacks[num].BoolValue); + controller.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); + } } #region IRoutingInputs Members @@ -79,7 +95,7 @@ namespace PepperDash.Essentials.DM Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); this.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); - + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = this.Name; } #endregion @@ -100,6 +116,10 @@ namespace PepperDash.Essentials.DM JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "DM Tx Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); /// /// Plugin device BridgeJoinMap constructor From 139ecc3e583c2fdddb0296012c11de8c2814806e Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Fri, 12 Aug 2022 17:32:54 -0500 Subject: [PATCH 104/202] fix: (wip) updated VideoCodecBase LinkToApis to resolve issue #983 with call status and directory not updating wtih bridge online status change --- .../VideoCodec/VideoCodecBase.cs | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index f9da46a5..12727c46 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -463,10 +463,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } SharingContentIsOnFeedback.FireUpdate(); - - trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); - - trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); }; } @@ -1042,9 +1038,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (!args.DeviceOnLine) return; - trilist.SetString(joinMap.DirectoryEntries.JoinNumber, "\xFC"); - UpdateDirectoryXSig(codec.CurrentDirectoryResult, - codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); + // TODO [ ] #981 + var clearBytes = XSigHelpers.ClearOutputs(); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); }; } @@ -1260,7 +1259,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec }); } - trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); + // TODO [ ] #983 + //trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); CallStatusChange += (sender, args) => { @@ -1364,9 +1364,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (!args.DeviceOnLine) return; - // TODO [ ] Issue #868 + // TODO [ ] #983 + Debug.Console(0, this, "LinkVideoCodecCallControlsToApi: device is {0}, IsInCall {1}", args.DeviceOnLine ? "online" : "offline", IsInCall); + trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); trilist.SetString(joinMap.CurrentCallData.JoinNumber, "\xFC"); - UpdateCallStatusXSig(); + trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); }; } From 12248c6393d752a43df8492448b87e322f0bc868 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Fri, 12 Aug 2022 17:36:38 -0500 Subject: [PATCH 105/202] fix: removed extra debug statements --- .../Essentials Devices Common/VideoCodec/VideoCodecBase.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 12727c46..bf7fe188 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1038,7 +1038,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (!args.DeviceOnLine) return; - // TODO [ ] #981 var clearBytes = XSigHelpers.ClearOutputs(); trilist.SetString(joinMap.DirectoryEntries.JoinNumber, Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); @@ -1259,8 +1258,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec }); } - // TODO [ ] #983 - //trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); + trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); CallStatusChange += (sender, args) => { From 0376943dac8fec4094fca5c0aca63b9b70ac0143 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Sat, 20 Aug 2022 15:18:39 -0400 Subject: [PATCH 106/202] Reworks the creation process for DM transmitters --- .../Transmitters/DmTx200Controller.cs | 3 +- .../Transmitters/DmTx201CController.cs | 5 +- .../Transmitters/DmTx201SController.cs | 3 +- .../Transmitters/DmTx401CController.cs | 3 +- .../Transmitters/DmTx4k202CController.cs | 3 +- .../Transmitters/DmTx4k302CController.cs | 7 +- .../Transmitters/DmTx4kz202CController.cs | 3 +- .../Transmitters/DmTx4kz302CController.cs | 3 +- .../Endpoints/Transmitters/DmTxHelpers.cs | 231 +++++++++--------- .../Transmitters/HDBaseTTxController.cs | 2 + 10 files changed, 135 insertions(+), 128 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx200Controller.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx200Controller.cs index c638ecb6..fe4454b9 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx200Controller.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx200Controller.cs @@ -97,10 +97,11 @@ namespace PepperDash.Essentials.DM /// /// /// - public DmTx200Controller(string key, string name, DmTx200C2G tx) + public DmTx200Controller(string key, string name, DmTx200C2G tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201CController.cs index 623391dc..660d2fec 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201CController.cs @@ -99,11 +99,12 @@ namespace PepperDash.Essentials.DM /// /// /// - /// - public DmTx201CController(string key, string name, DmTx201C tx) + /// + public DmTx201CController(string key, string name, DmTx201C tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201SController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201SController.cs index 7c4b0d34..e42ecb4b 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201SController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201SController.cs @@ -102,10 +102,11 @@ namespace PepperDash.Essentials.DM /// /// /// - public DmTx201SController(string key, string name, DmTx201S tx) + public DmTx201SController(string key, string name, DmTx201S tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs index 1407b70e..ae4e2c31 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs @@ -111,10 +111,11 @@ namespace PepperDash.Essentials.DM /// /// /// - public DmTx401CController(string key, string name, DmTx401C tx) + public DmTx401CController(string key, string name, DmTx401C tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiIn = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.HDMI, this, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k202CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k202CController.cs index 729744b9..387562e4 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k202CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k202CController.cs @@ -96,10 +96,11 @@ namespace PepperDash.Essentials.DM } } - public DmTx4k202CController(string key, string name, DmTx4k202C tx) + public DmTx4k202CController(string key, string name, DmTx4k202C tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k302CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k302CController.cs index 3e716f60..87906735 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k302CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k302CController.cs @@ -101,11 +101,12 @@ namespace PepperDash.Essentials.DM { return new RoutingPortCollection { DmOut, HdmiLoopOut }; } - } - public DmTx4k302CController(string key, string name, DmTx4k302C tx) + } + public DmTx4k302CController(string key, string name, DmTx4k302C tx, bool preventRegistration) : base(key, name, tx) { - Tx = tx; + Tx = tx; + PreventRegistration = preventRegistration; HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs index a241d60d..b9f521c6 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs @@ -86,10 +86,11 @@ namespace PepperDash.Essentials.DM return new RoutingPortCollection { DmOut, HdmiLoopOut }; } } - public DmTx4kz202CController(string key, string name, DmTx4kz202C tx) + public DmTx4kz202CController(string key, string name, DmTx4kz202C tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs index 70df8259..de60d80e 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs @@ -91,10 +91,11 @@ namespace PepperDash.Essentials.DM return new RoutingPortCollection { DmOut, HdmiLoopOut }; } } - public DmTx4kz302CController(string key, string name, DmTx4kz302C tx) + public DmTx4kz302CController(string key, string name, DmTx4kz302C tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs index d04f462c..d707ebd3 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs @@ -20,6 +20,63 @@ namespace PepperDash.Essentials.DM { public class DmTxHelper { + + public static BasicDmTxControllerBase GetDmTxForChassisWithoutIpId(string key, string name, string typeName, DMInput dmInput) + { + if (typeName.StartsWith("dmtx200")) + return new DmTx200Controller(key, name, new DmTx200C2G(dmInput), true); + if (typeName.StartsWith("dmtx201c")) + return new DmTx201CController(key, name, new DmTx201C(dmInput), true); + if (typeName.StartsWith("dmtx201s")) + return new DmTx201SController(key, name, new DmTx201S(dmInput), true); + if (typeName.StartsWith("dmtx4k100")) + return new DmTx4k100Controller(key, name, new DmTx4K100C1G(dmInput)); + if (typeName.StartsWith("dmtx4kz100")) + return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(dmInput)); + if (typeName.StartsWith("dmtx4k202")) + return new DmTx4k202CController(key, name, new DmTx4k202C(dmInput), true); + if (typeName.StartsWith("dmtx4kz202")) + return new DmTx4kz202CController(key, name, new DmTx4kz202C(dmInput), true); + if (typeName.StartsWith("dmtx4k302")) + return new DmTx4k302CController(key, name, new DmTx4k302C(dmInput), true); + if (typeName.StartsWith("dmtx4kz302")) + return new DmTx4kz302CController(key, name, new DmTx4kz302C(dmInput), true); + if (typeName.StartsWith("dmtx401")) + return new DmTx401CController(key, name, new DmTx401C(dmInput), true); + if (typeName.StartsWith("hdbasettx")) + new HDBaseTTxController(key, name, new HDTx3CB(dmInput)); + + return null; + } + + public static BasicDmTxControllerBase GetDmTxForChassisWithIpId(string key, string name, string typeName, uint ipid, DMInput dmInput) + { + if (typeName.StartsWith("dmtx200")) + return new DmTx200Controller(key, name, new DmTx200C2G(ipid, dmInput), true); + if (typeName.StartsWith("dmtx201c")) + return new DmTx201CController(key, name, new DmTx201C(ipid, dmInput), true); + if (typeName.StartsWith("dmtx201s")) + return new DmTx201SController(key, name, new DmTx201S(ipid, dmInput), true); + if (typeName.StartsWith("dmtx4k100")) + return new DmTx4k100Controller(key, name, new DmTx4K100C1G(ipid, dmInput)); + if (typeName.StartsWith("dmtx4kz100")) + return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(ipid, dmInput)); + if (typeName.StartsWith("dmtx4k202")) + return new DmTx4k202CController(key, name, new DmTx4k202C(ipid, dmInput), true); + if (typeName.StartsWith("dmtx4kz202")) + return new DmTx4kz202CController(key, name, new DmTx4kz202C(ipid, dmInput), true); + if (typeName.StartsWith("dmtx4k302")) + return new DmTx4k302CController(key, name, new DmTx4k302C(ipid, dmInput), true); + if (typeName.StartsWith("dmtx4kz302")) + return new DmTx4kz302CController(key, name, new DmTx4kz302C(ipid, dmInput), true); + if (typeName.StartsWith("dmtx401")) + return new DmTx401CController(key, name, new DmTx401C(ipid, dmInput), true); + if (typeName.StartsWith("hdbasettx")) + return new HDBaseTTxController(key, name, new HDTx3CB(ipid, dmInput)); + + return null; + } + /// /// A factory method for various DmTxControllers /// @@ -27,7 +84,7 @@ namespace PepperDash.Essentials.DM /// /// /// - public static BasicDmTxControllerBase GetDmTxController(string key, string name, string typeName, DmTxPropertiesConfig props) + public static BasicDmTxControllerBase GetDmTxController(string key, string name, string typeName, DmTxPropertiesConfig props) { // switch on type name... later... @@ -42,23 +99,21 @@ namespace PepperDash.Essentials.DM try { if(typeName.StartsWith("dmtx200")) - return new DmTx200Controller(key, name, new DmTx200C2G(ipid, Global.ControlSystem)); - if (typeName.StartsWith("dmtx4kz100")) - return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(ipid, Global.ControlSystem)); + return new DmTx200Controller(key, name, new DmTx200C2G(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx201c")) - return new DmTx201CController(key, name, new DmTx201C(ipid, Global.ControlSystem)); + return new DmTx201CController(key, name, new DmTx201C(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx201s")) - return new DmTx201SController(key, name, new DmTx201S(ipid, Global.ControlSystem)); + return new DmTx201SController(key, name, new DmTx201S(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx4k202")) - return new DmTx4k202CController(key, name, new DmTx4k202C(ipid, Global.ControlSystem)); + return new DmTx4k202CController(key, name, new DmTx4k202C(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx4kz202")) - return new DmTx4kz202CController(key, name, new DmTx4kz202C(ipid, Global.ControlSystem)); + return new DmTx4kz202CController(key, name, new DmTx4kz202C(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx4k302")) - return new DmTx4k302CController(key, name, new DmTx4k302C(ipid, Global.ControlSystem)); + return new DmTx4k302CController(key, name, new DmTx4k302C(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx4kz302")) - return new DmTx4kz302CController(key, name, new DmTx4kz302C(ipid, Global.ControlSystem)); + return new DmTx4kz302CController(key, name, new DmTx4kz302C(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx401")) - return new DmTx401CController(key, name, new DmTx401C(ipid, Global.ControlSystem)); + return new DmTx401CController(key, name, new DmTx401C(ipid, Global.ControlSystem), false); Debug.Console(0, "{1} WARNING: Cannot create DM-TX of type: '{0}'", typeName, key); } catch (Exception e) @@ -70,12 +125,12 @@ namespace PepperDash.Essentials.DM var parentDev = DeviceManager.GetDeviceForKey(pKey); DMInput dmInput; - bool isCpu3 = false; + BasicDmTxControllerBase tx; - if (parentDev is IDmSwitch) + if (parentDev is DmChassisController) { // Get the Crestron chassis and link stuff up - var switchDev = (parentDev as IDmSwitch); + var switchDev = (parentDev as DmChassisController); var chassis = switchDev.Chassis; //Check that the input is within range of this chassis' possible inputs @@ -90,15 +145,31 @@ namespace PepperDash.Essentials.DM switchDev.TxDictionary.Add(num, key); dmInput = chassis.Inputs[num]; - //Determine if IpId is needed for this chassis type - if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || - chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || - chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || - chassis is DmMd128x128 || chassis is DmMd64x64) - { - isCpu3 = true; - } + try + { + //Determine if IpId is needed for this chassis type + if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || + chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || + chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || + chassis is DmMd128x128 || chassis is DmMd64x64) + { + tx = GetDmTxForChassisWithoutIpId(key, name, typeName, dmInput); + Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); + tx.IsOnline.SetValueFunc(() => switchDev.InputEndpointOnlineFeedbacks[num].BoolValue); + switchDev.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => tx.IsOnline.FireUpdate(); + return tx; + } + else + { + return GetDmTxForChassisWithIpId(key, name, typeName, ipid, dmInput); + } + } + catch (Exception e) + { + Debug.Console(0, "[{0}] WARNING: Cannot create DM-TX device for chassis: {1}", key, e); + return null; + } } else if(parentDev is DmpsRoutingController) { @@ -126,6 +197,27 @@ namespace PepperDash.Essentials.DM Debug.Console(0, "Cannot create DMPS device '{0}'. Input number '{1}' is not a DM input", key, num); return null; } + + try + { + if(Global.ControlSystemIsDmps4kType) + { + tx = GetDmTxForChassisWithoutIpId(key, name, typeName, dmInput); + Debug.Console(0, "DM endpoint output {0} is for DMPS3-4K, changing online feedback to chassis", num); + tx.IsOnline.SetValueFunc(() => dmpsDev.InputEndpointOnlineFeedbacks[num].BoolValue); + dmpsDev.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => tx.IsOnline.FireUpdate(); + return tx; + } + else + { + return GetDmTxForChassisWithIpId(key, name, typeName, ipid, dmInput); + } + } + catch (Exception e) + { + Debug.Console(0, "[{0}] WARNING: Cannot create DM-TX device for dmps: {1}", key, e); + return null; + } } else @@ -133,67 +225,6 @@ namespace PepperDash.Essentials.DM Debug.Console(0, "Cannot create DM device '{0}'. '{1}' is not a processor, DM Chassis or DMPS.", key, pKey); return null; } - - try - { - // Must use different constructor for CPU3 or DMPS3-4K types. No IPID - if (isCpu3 || (parentDev is DmpsRoutingController && Global.ControlSystemIsDmps4kType)) - { - if (typeName.StartsWith("dmtx200")) - return new DmTx200Controller(key, name, new DmTx200C2G(dmInput)); - if (typeName.StartsWith("dmtx201c")) - return new DmTx201CController(key, name, new DmTx201C(dmInput)); - if (typeName.StartsWith("dmtx201s")) - return new DmTx201SController(key, name, new DmTx201S(dmInput)); - if (typeName.StartsWith("dmtx4k100")) - return new DmTx4k100Controller(key, name, new DmTx4K100C1G(dmInput)); - if (typeName.StartsWith("dmtx4kz100")) - return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(dmInput)); - if (typeName.StartsWith("dmtx4k202")) - return new DmTx4k202CController(key, name, new DmTx4k202C(dmInput)); - if (typeName.StartsWith("dmtx4kz202")) - return new DmTx4kz202CController(key, name, new DmTx4kz202C(dmInput)); - if (typeName.StartsWith("dmtx4k302")) - return new DmTx4k302CController(key, name, new DmTx4k302C(dmInput)); - if (typeName.StartsWith("dmtx4kz302")) - return new DmTx4kz302CController(key, name, new DmTx4kz302C(dmInput)); - if (typeName.StartsWith("dmtx401")) - return new DmTx401CController(key, name, new DmTx401C(dmInput)); - if (typeName.StartsWith("hdbasettx")) - return new HDBaseTTxController(key, name, new HDTx3CB(dmInput)); - } - else - { - if (typeName.StartsWith("dmtx200")) - return new DmTx200Controller(key, name, new DmTx200C2G(ipid, dmInput)); - if (typeName.StartsWith("dmtx201c")) - return new DmTx201CController(key, name, new DmTx201C(ipid, dmInput)); - if (typeName.StartsWith("dmtx201s")) - return new DmTx201SController(key, name, new DmTx201S(ipid, dmInput)); - if (typeName.StartsWith("dmtx4k100")) - return new DmTx4k100Controller(key, name, new DmTx4K100C1G(ipid, dmInput)); - if (typeName.StartsWith("dmtx4kz100")) - return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(ipid, dmInput)); - if (typeName.StartsWith("dmtx4k202")) - return new DmTx4k202CController(key, name, new DmTx4k202C(ipid, dmInput)); - if (typeName.StartsWith("dmtx4kz202")) - return new DmTx4kz202CController(key, name, new DmTx4kz202C(ipid, dmInput)); - if (typeName.StartsWith("dmtx4k302")) - return new DmTx4k302CController(key, name, new DmTx4k302C(ipid, dmInput)); - if (typeName.StartsWith("dmtx4kz302")) - return new DmTx4kz302CController(key, name, new DmTx4kz302C(ipid, dmInput)); - if (typeName.StartsWith("dmtx401")) - return new DmTx401CController(key, name, new DmTx401C(ipid, dmInput)); - if (typeName.StartsWith("hdbasettx")) - return new HDBaseTTxController(key, name, new HDTx3CB(ipid, dmInput)); - } - } - catch (Exception e) - { - Debug.Console(0, "[{0}] WARNING: Cannot create DM-TX device: {1}", key, e); - } - - return null; } } @@ -223,40 +254,6 @@ namespace PepperDash.Essentials.DM { AddToFeedbackList(ActiveVideoInputFeedback); - // if wired to a chassis or DMPS, skip registration step in base class - if (hardware.DMInput != null) - { - this.PreventRegistration = true; - - var parentDev = DeviceManager.GetDeviceForKey(key); - var num = hardware.DMInput.Number; - - //If Dmps4K, change online feedback to chassis, tx feedback does not work - if (parentDev is DmpsRoutingController && Global.ControlSystemIsDmps4kType) - { - var dmps = parentDev as DmpsRoutingController; - Debug.Console(0, "DM endpoint input {0} is for Dmps4k, changing online feedback to chassis", num); - IsOnline.SetValueFunc(() => dmps.InputEndpointOnlineFeedbacks[num].BoolValue); - dmps.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); - } - //If Cpu3 Chassis, change online feedback to chassis, tx feedback does not work - else if (parentDev is DmChassisController) - { - var controller = parentDev as DmChassisController; - var chassis = controller.Chassis; - - if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || - chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || - chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || - chassis is DmMd128x128 || chassis is DmMd64x64) - { - Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); - IsOnline.SetValueFunc(() => controller.InputEndpointOnlineFeedbacks[num].BoolValue); - controller.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); - } - } - } - IsOnline.OutputChange += (currentDevice, args) => { foreach (var feedback in Feedbacks) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs index d7a78237..bedf1aad 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs @@ -27,6 +27,8 @@ namespace PepperDash.Essentials.DM public HDBaseTTxController(string key, string name, HDTx3CB tx) : base(key, name, tx) { + PreventRegistration = true; + HdmiIn = new RoutingInputPort(DmPortName.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, null, this) { Port = tx }; From 68a0157fbe1ec2172a14426be3d47f1477d59c92 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 30 Aug 2022 13:57:53 -0600 Subject: [PATCH 107/202] fix: add missing interface --- .../Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs index c7f68e8b..41616d96 100644 --- a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs +++ b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs @@ -7,7 +7,7 @@ using PepperDash.Essentials.Room.Config; namespace PepperDash.Essentials { - public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay + public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay, IHasCurrentVolumeControls { bool ExcludeFromGlobalFunctions { get; } From 074ee190ade91ff749ef205044dddec8bd873ca2 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 30 Aug 2022 21:53:41 -0500 Subject: [PATCH 108/202] feat: added cen-io-ir-104 device and factory --- .../Crestron IO/Ir/CenIoIr104Controller.cs | 62 +++++++++++++++++++ .../PepperDash_Essentials_Core.csproj | 1 + 2 files changed, 63 insertions(+) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs new file mode 100644 index 00000000..413f3568 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs @@ -0,0 +1,62 @@ +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 +{ + /// + /// Wrapper class for CEN-IO-IR-104 module + /// + [Description("Wrapper class for the CEN-IO-IR-104 module")] + public class CenIoIr104Controller : EssentialsDevice, IIROutputPorts + { + public CenIoIr104 Ir104 { get; private set; } + + public CenIoIr104Controller(string key, string name, CenIoIr104 ir104) + : base(key, name) + { + Ir104 = ir104; + } + + #region IDigitalInputPorts Members + + public CrestronCollection IROutputPorts + { + get { return Ir104.IROutputPorts; } + } + + public int NumberOfIROutputPorts + { + get { return Ir104.NumberOfIROutputPorts; } + } + + #endregion + } + + public class CenIoIr104ControllerFactory : EssentialsDeviceFactory + { + public CenIoIr104ControllerFactory() + { + TypeNames = new List() { "cenioir104" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new CEN-IR-104 Device"); + + var control = CommFactory.GetControlPropertiesConfig(dc); + var ipid = control.IpIdInt; + + return new CenIoIr104Controller(dc.Key, dc.Name, new Crestron.SimplSharpPro.GeneralIO.CenIoIr104(ipid, Global.ControlSystem)); + } + } + +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index cdf6406c..df9b8115 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -183,6 +183,7 @@ + From 122abc56e599469079467a9923266ce8252d4dd3 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 30 Aug 2022 22:02:47 -0500 Subject: [PATCH 109/202] fix: added null checks in BuildDevice with debug statements if null --- .../Crestron IO/Ir/CenIoIr104Controller.cs | 51 +++++++++++++++---- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs index 413f3568..c516c03e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs @@ -16,46 +16,77 @@ namespace PepperDash.Essentials.Core /// Wrapper class for CEN-IO-IR-104 module /// [Description("Wrapper class for the CEN-IO-IR-104 module")] - public class CenIoIr104Controller : EssentialsDevice, IIROutputPorts - { - public CenIoIr104 Ir104 { get; private set; } + public class CenIoIr104Controller : EssentialsDevice, IIROutputPorts + { + private readonly CenIoIr104 _ir104; + /// + /// Constructor + /// + /// + /// + /// public CenIoIr104Controller(string key, string name, CenIoIr104 ir104) : base(key, name) { - Ir104 = ir104; + _ir104 = ir104; } #region IDigitalInputPorts Members + /// + /// IR port collection + /// public CrestronCollection IROutputPorts { - get { return Ir104.IROutputPorts; } + get { return _ir104.IROutputPorts; } } + /// + /// Number of relay ports property + /// public int NumberOfIROutputPorts { - get { return Ir104.NumberOfIROutputPorts; } + get { return _ir104.NumberOfIROutputPorts; } } #endregion } + /// + /// CEN-IO-IR-104 controller fatory + /// public class CenIoIr104ControllerFactory : EssentialsDeviceFactory { + /// + /// Constructor + /// public CenIoIr104ControllerFactory() { TypeNames = new List() { "cenioir104" }; } + /// + /// Build device CEN-IO-IR-104 + /// + /// + /// public override EssentialsDevice BuildDevice(DeviceConfig dc) { - Debug.Console(1, "Factory Attempting to create new CEN-IR-104 Device"); + 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"); + return null; + } - var control = CommFactory.GetControlPropertiesConfig(dc); var ipid = control.IpIdInt; - - return new CenIoIr104Controller(dc.Key, dc.Name, new Crestron.SimplSharpPro.GeneralIO.CenIoIr104(ipid, Global.ControlSystem)); + 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; } } From 457494128832efb0f4aa22a9cd1977921b6c9362 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 30 Aug 2022 22:11:33 -0500 Subject: [PATCH 110/202] fix: updated debug statement for DinCenCnController class referencing building a temp sensor device --- .../Crestron IO/DinCenCn/DinCenCnController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/DinCenCnController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/DinCenCnController.cs index 68fedc82..7e9179fe 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/DinCenCnController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/DinCenCnController.cs @@ -34,7 +34,7 @@ namespace PepperDash.Essentials.Core public override EssentialsDevice BuildDevice(DeviceConfig dc) { - Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device"); + Debug.Console(1, "Factory Attempting to create new DIN-CEN-CN2 Device"); var control = CommFactory.GetControlPropertiesConfig(dc); var ipid = control.IpIdInt; From fb689c4484e9f95f58adb83295a75e35ace8217e Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 31 Aug 2022 14:43:58 -0500 Subject: [PATCH 111/202] fix: updated CEN-IO classes inheriting from EssentialsDevice to CrestronGenericBaseDevice to resolve activation issues --- .../Inputs/CenIoDigIn104Controller.cs | 17 ++- .../Crestron IO/Ir/CenIoIr104Controller.cs | 120 +++++++++--------- .../Crestron IO/Relay/CenIoRy104Controller.cs | 8 +- 3 files changed, 76 insertions(+), 69 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/CenIoDigIn104Controller.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/CenIoDigIn104Controller.cs index 5112f3aa..bdbcc2e9 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/CenIoDigIn104Controller.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/CenIoDigIn104Controller.cs @@ -16,7 +16,7 @@ namespace PepperDash.Essentials.Core /// Wrapper class for CEN-IO-DIGIN-104 digital 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; } @@ -52,10 +52,17 @@ namespace PepperDash.Essentials.Core { Debug.Console(1, "Factory Attempting to create new CEN-DIGIN-104 Device"); - var control = CommFactory.GetControlPropertiesConfig(dc); - var ipid = control.IpIdInt; - - return new CenIoDigIn104Controller(dc.Key, dc.Name, new Crestron.SimplSharpPro.GeneralIO.CenIoDi104(ipid, Global.ControlSystem)); + var control = CommFactory.GetControlPropertiesConfig(dc); + if (control == null) + { + Debug.Console(1, "Factory failed to create a new CEN-DIGIN-104 Device, control properties not found"); + return null; + } + var ipid = control.IpIdInt; + if (ipid != 0) return new CenIoDigIn104Controller(dc.Key, dc.Name, new CenIoDi104(ipid, Global.ControlSystem)); + + Debug.Console(1, "Factory failed to create a new CEN-IO-IR-104 Device using IP-ID-{0}", ipid); + return null; } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs index c516c03e..3fa45dd7 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs @@ -1,93 +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 -{ - /// - /// Wrapper class for CEN-IO-IR-104 module - /// - [Description("Wrapper class for the CEN-IO-IR-104 module")] - public class CenIoIr104Controller : EssentialsDevice, IIROutputPorts +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 +{ + /// + /// Wrapper class for CEN-IO-IR-104 module + /// + [Description("Wrapper class for the CEN-IO-IR-104 module")] + public class CenIoIr104Controller : CrestronGenericBaseDevice, IIROutputPorts { - private readonly CenIoIr104 _ir104; - + private readonly CenIoIr104 _ir104; + /// /// Constructor /// /// /// - /// - public CenIoIr104Controller(string key, string name, CenIoIr104 ir104) - : base(key, name) - { - _ir104 = ir104; - } - + /// + public CenIoIr104Controller(string key, string name, CenIoIr104 ir104) + : base(key, name, ir104) + { + _ir104 = ir104; + } + #region IDigitalInputPorts Members /// /// IR port collection /// - public CrestronCollection IROutputPorts - { - get { return _ir104.IROutputPorts; } + public CrestronCollection IROutputPorts + { + get { return _ir104.IROutputPorts; } } /// /// Number of relay ports property /// - public int NumberOfIROutputPorts - { - get { return _ir104.NumberOfIROutputPorts; } - } - + public int NumberOfIROutputPorts + { + get { return _ir104.NumberOfIROutputPorts; } + } + #endregion - } - + } + /// /// CEN-IO-IR-104 controller fatory - /// - public class CenIoIr104ControllerFactory : EssentialsDeviceFactory - { + /// + public class CenIoIr104ControllerFactory : EssentialsDeviceFactory + { /// /// Constructor - /// - public CenIoIr104ControllerFactory() - { - TypeNames = new List() { "cenioir104" }; - } - + /// + public CenIoIr104ControllerFactory() + { + TypeNames = new List() { "cenioir104" }; + } + /// /// Build device CEN-IO-IR-104 /// /// - /// - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.Console(1, "Factory Attempting to create new CEN-IO-IR-104 Device"); - + /// + 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"); + Debug.Console(1, "Factory failed to create a new CEN-IO-IR-104 Device, control properties not found"); return null; - } - - var ipid = control.IpIdInt; + } + + 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; - } - } - + return null; + } + } + } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/CenIoRy104Controller.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/CenIoRy104Controller.cs index 19ca8438..e9963f4d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/CenIoRy104Controller.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/CenIoRy104Controller.cs @@ -10,7 +10,7 @@ namespace PepperDash.Essentials.Core /// Wrapper class for 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; @@ -21,7 +21,7 @@ namespace PepperDash.Essentials.Core /// /// public CenIoRy104Controller(string key, string name, CenIoRy104 ry104) - : base(key, name) + : base(key, name, ry104) { _ry104 = ry104; } @@ -62,8 +62,8 @@ namespace PepperDash.Essentials.Core var controlPropertiesConfig = CommFactory.GetControlPropertiesConfig(dc); if (controlPropertiesConfig == null) - { - Debug.Console(1, "Factory failed to create a new CEN-IO-RY-104 Device"); + { + Debug.Console(1, "Factory failed to create a new CEN-IO-RY-104 Device, control properties not found"); return null; } From d7cccc0709294847c01582b29616a342d90d7d89 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Sep 2022 11:47:52 -0600 Subject: [PATCH 112/202] 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. --- .../Routing/IRoutingInputsExtensions.cs | 71 +++++++++++++++++-- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index 0c375825..4beaa37d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -11,12 +11,34 @@ using PepperDash.Core; namespace PepperDash.Essentials.Core { + public class RouteRequest + { + public IRoutingSink Destination {get; set;} + public IRoutingOutputs Source {get; set;} + public eRoutingSignalType SignalType {get; set;} + + public void HandleCooldown(object sender, FeedbackEventArgs args) + { + var coolingDevice = sender as IWarmingCooling; + + if(args.BoolValue == false) + { + Destination.ReleaseAndMakeRoute(Source, SignalType); + + if(sender == null) return; + + coolingDevice.IsCoolingDownFeedback.OutputChange -= HandleCooldown; + } + } + } + /// /// Extensions added to any IRoutingInputs classes to provide discovery-based routing /// on those destinations. /// public static class IRoutingInputsExtensions { + private static Dictionary RouteRequests = new Dictionary(); /// /// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute /// and then attempts a new Route and if sucessful, stores that RouteDescriptor @@ -24,16 +46,51 @@ namespace PepperDash.Essentials.Core /// public static void ReleaseAndMakeRoute(this IRoutingSink destination, IRoutingOutputs source, eRoutingSignalType signalType) { - destination.ReleaseRoute(); + var routeRequest = new RouteRequest { + Destination = destination, + Source = source, + SignalType = signalType + }; - if (source == null) return; - var newRoute = destination.GetRouteToSource(source, signalType); - if (newRoute == null) return; - RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(newRoute); - Debug.Console(2, destination, "Executing full route"); - newRoute.ExecuteRoutes(); + var coolingDevice = destination as IWarmingCooling; + + RouteRequest existingRouteRequest; + + //We already have a route request for this device, and it's a cooling device and is cooling + if (RouteRequests.TryGetValue(destination.Key, out existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) + { + coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; + + coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; + + RouteRequests[destination.Key] = routeRequest; + return; + } + + //New Request + if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) + { + coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; + + RouteRequests.Add(destination.Key, routeRequest); + return; + } + + 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(); + } + /// /// Will release the existing route on the destination, if it is found in /// RouteDescriptorCollection.DefaultCollection From 358f44cfe598e17fc55b7fa09d3348842b206396 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Sep 2022 11:57:40 -0600 Subject: [PATCH 113/202] refactor: remove completed request from dictionary --- .../Routing/IRoutingInputsExtensions.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index 4beaa37d..2dbf895a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -58,24 +58,31 @@ namespace PepperDash.Essentials.Core //We already have a route request for this device, and it's a cooling device and is cooling if (RouteRequests.TryGetValue(destination.Key, out existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) - { + { coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; RouteRequests[destination.Key] = routeRequest; 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); return; } + if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false) + { + RouteRequests.Remove(destination.Key); + } + destination.ReleaseRoute(); RunRouteRequest(routeRequest); From 7fe2d04d315d8e6a63e7a7914566406e2ff749cf Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Sep 2022 12:29:19 -0600 Subject: [PATCH 114/202] fix: add removal of RouteRequest when calling ReleaseRoute --- .../Routing/IRoutingInputsExtensions.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index 2dbf895a..bd5aff73 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -105,6 +105,17 @@ namespace PepperDash.Essentials.Core /// public static void ReleaseRoute(this IRoutingSink destination) { + RouteRequest existingRequest; + + if (RouteRequests.TryGetValue(destination.Key, out existingRequest) && destination is IWarmingCooling) + { + var coolingDevice = destination as IWarmingCooling; + + coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown; + } + + RouteRequests.Remove(destination.Key); + var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination); if (current != null) { From c4a23e08871aaad758ffe197ec5a1498bbe47541 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 2 Sep 2022 11:19:18 -0600 Subject: [PATCH 115/202] feat(essentials): Adds RoomUiBehaviorConfig for disabling activity buttons --- .../Room/Config/EssentialsRoomConfig.cs | 9 ++++ .../Display/MockDisplay.cs | 47 +++++++++++++++---- .../Routing/IRoutingInputsExtensions.cs | 14 ++++-- 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs index 5a2bd34f..b0ad2ae1 100644 --- a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs +++ b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs @@ -202,6 +202,9 @@ namespace PepperDash.Essentials.Room.Config [JsonProperty("fusion")] public EssentialsRoomFusionConfig Fusion { get; set; } + [JsonProperty("essentialsRoomUiBehaviorConfig", NullValueHandling=NullValueHandling.Ignore)] + public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; } + [JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")] public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; } @@ -218,6 +221,12 @@ namespace PepperDash.Essentials.Room.Config } } + public class EssentialsRoomUiBehaviorConfig + { + [JsonProperty("disableActivityButtonsWhileWarmingCooling")] + public bool DisableActivityButtonsWhileWarmingCooling { get; set; } + } + public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig { [JsonProperty("defaultAudioKey")] diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs index 4ac61943..266c1cbb 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs @@ -30,11 +30,40 @@ namespace PepperDash.Essentials.Core bool _PowerIsOn; bool _IsWarmingUp; - bool _IsCoolingDown; - - protected override Func PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } } - protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } } - protected override Func IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } } + bool _IsCoolingDown; + + protected override Func PowerIsOnFeedbackFunc + { + get + { + return () => + { + Debug.Console(2, this, "*************************************************** Display Power is {0}", _PowerIsOn ? "on" : "off"); + return _PowerIsOn; + }; + } } + protected override Func IsCoolingDownFeedbackFunc + { + get + { + return () => + { + Debug.Console(2, this, "*************************************************** {0}", _IsCoolingDown ? "Display is cooling down" : "Display has finished cooling down"); + return _IsCoolingDown; + }; + } + } + protected override Func IsWarmingUpFeedbackFunc + { + get + { + return () => + { + Debug.Console(2, this, "*************************************************** {0}", _IsWarmingUp ? "Display is warming up" : "Display has finished warming up"); + return _IsWarmingUp; + }; + } + } protected override Func CurrentInputFeedbackFunc { get { return () => "Not Implemented"; } } int VolumeHeldRepeatInterval = 200; @@ -61,7 +90,7 @@ namespace PepperDash.Essentials.Core MuteFeedback = new BoolFeedback("MuteOn", () => _IsMuted); WarmupTime = 10000; - CooldownTime = 5000; + CooldownTime = 10000; } public override void PowerOn() @@ -88,15 +117,15 @@ namespace PepperDash.Essentials.Core if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) { _IsCoolingDown = true; - _PowerIsOn = false; - PowerIsOnFeedback.InvokeFireUpdate(); IsCoolingDownFeedback.InvokeFireUpdate(); // Fake cool-down cycle CooldownTimer = new CTimer(o => { Debug.Console(2, this, "Cooldown timer ending"); _IsCoolingDown = false; - IsCoolingDownFeedback.InvokeFireUpdate(); + IsCoolingDownFeedback.InvokeFireUpdate(); + _PowerIsOn = false; + PowerIsOnFeedback.InvokeFireUpdate(); }, CooldownTime); } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index bd5aff73..d371c2d6 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -58,12 +58,15 @@ namespace PepperDash.Essentials.Core //We already have a route request for this device, and it's a cooling device and is cooling if (RouteRequests.TryGetValue(destination.Key, out existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) - { + { coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; - RouteRequests[destination.Key] = routeRequest; + 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; } @@ -74,13 +77,16 @@ namespace PepperDash.Essentials.Core coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; - RouteRequests.Add(destination.Key, routeRequest); + 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); + 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(); From d01be57f814ad69f7b1456f3da8b556c5881c757 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 2 Sep 2022 13:54:34 -0600 Subject: [PATCH 116/202] feat: add TouchpanelBase class and initial implementation --- .../UI/EssentialsTouchpanelController.cs | 199 +------------ .../PepperDash_Essentials_Core.csproj | 1 + .../UI/TouchpanelBase.cs | 270 ++++++++++++++++++ 3 files changed, 278 insertions(+), 192 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs diff --git a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs index 441381bd..24bc33db 100644 --- a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs +++ b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs @@ -11,10 +11,11 @@ using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.PageManagers; +using PepperDash.Essentials.Core.UI; namespace PepperDash.Essentials { - public class EssentialsTouchpanelController : EssentialsDevice, IHasBasicTriListWithSmartObject + public class EssentialsTouchpanelController : TouchpanelBase { private CrestronTouchpanelPropertiesConfig _propertiesConfig; @@ -26,189 +27,29 @@ namespace PepperDash.Essentials public EssentialsTouchpanelController(string key, string name, Tswx52ButtonVoiceControl tsw, string projectName, string sgdPath) - : base(key, name) + : base(key, name, tsw, sgdPath) { - Panel = tsw; - - if (!string.IsNullOrEmpty(sgdPath)) - Panel.LoadSmartObjects(sgdPath); - else - Debug.Console(1, this, "No SGD file path defined"); - - - - tsw.SigChange += Panel_SigChange; } public EssentialsTouchpanelController(string key, string name, Dge100 dge, string projectName, string sgdPath) - : base(key, name) + : base(key, name, dge, sgdPath) { - Panel = dge; - - if (!string.IsNullOrEmpty(sgdPath)) - Panel.LoadSmartObjects(sgdPath); - else - Debug.Console(1, this, "No SGD file path defined"); - - dge.SigChange += Panel_SigChange; } /// /// Config constructor /// public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id) - : base(key, name) + : base(key, name, type, props, id) { - _propertiesConfig = props; - - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating touchpanel hardware..."); - type = type.ToLower(); - try - { - if (type == "crestronapp") - { - var app = new CrestronApp(id, Global.ControlSystem); - app.ParameterProjectName.Value = props.ProjectName; - Panel = app; - } - else if (type == "xpanel") - Panel = new XpanelForSmartGraphics(id, Global.ControlSystem); - else if (type == "tsw550") - Panel = new Tsw550(id, Global.ControlSystem); - else if (type == "tsw552") - Panel = new Tsw552(id, Global.ControlSystem); - else if (type == "tsw560") - Panel = new Tsw560(id, Global.ControlSystem); - else if (type == "tsw750") - Panel = new Tsw750(id, Global.ControlSystem); - else if (type == "tsw752") - Panel = new Tsw752(id, Global.ControlSystem); - else if (type == "tsw760") - Panel = new Tsw760(id, Global.ControlSystem); - else if (type == "tsw1050") - Panel = new Tsw1050(id, Global.ControlSystem); - else if (type == "tsw1052") - Panel = new Tsw1052(id, Global.ControlSystem); - else if (type == "tsw1060") - Panel = new Tsw1060(id, Global.ControlSystem); - else if (type == "tsw570") - Panel = new Tsw570(id, Global.ControlSystem); - else if (type == "tsw770") - Panel = new Tsw770(id, Global.ControlSystem); - else if (type == "ts770") - Panel = new Ts770(id, Global.ControlSystem); - else if (type == "tsw1070") - Panel = new Tsw1070(id, Global.ControlSystem); - else if (type == "ts1070") - Panel = new Ts1070(id, Global.ControlSystem); - else - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW controller with type '{0}'", type); - return; - } - } - catch (Exception e) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message); - return; - } - - // Reserved sigs - if (Panel is TswFt5ButtonSystem) - { - var tsw = Panel as TswFt5ButtonSystem; - tsw.ExtenderSystemReservedSigs.Use(); - tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange - += ExtenderSystemReservedSigs_DeviceExtenderSigChange; - - tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange); - - } - - if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success) - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Registration failed. Continuing, but panel may not function: {0}", Panel.RegistrationFailureReason); - - // Give up cleanly if SGD is not present. - var sgdName = Global.FilePathPrefix + "sgd" + Global.DirectorySeparator + props.SgdFile; - if (!File.Exists(sgdName)) - { - Debug.Console(0, this, "Smart object file '{0}' not present in User folder. Looking for embedded file", sgdName); - - sgdName = Global.ApplicationDirectoryPathPrefix + Global.DirectorySeparator + "SGD" + Global.DirectorySeparator + props.SgdFile; - - if (!File.Exists(sgdName)) - { - Debug.Console(0, this, "Unable to find SGD file '{0}' in User sgd or application SGD folder. Exiting touchpanel load.", sgdName); - return; - } - } - - Panel.LoadSmartObjects(sgdName); - Panel.SigChange += Panel_SigChange; - - AddPostActivationAction(() => - { - // Check for IEssentialsRoomCombiner in DeviceManager and if found, subscribe to its event - var roomCombiner = DeviceManager.AllDevices.FirstOrDefault((d) => d is IEssentialsRoomCombiner) as IEssentialsRoomCombiner; - - if (roomCombiner != null) - { - // Subscribe to the even - roomCombiner.RoomCombinationScenarioChanged += new EventHandler(roomCombiner_RoomCombinationScenarioChanged); - - // Connect to the initial roomKey - if (roomCombiner.CurrentScenario != null) - { - // Use the current scenario - DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); - } - else - { - // Current Scenario not yet set. Use default - SetupPanelDrivers(_propertiesConfig.DefaultRoomKey); - } - } - else - { - // No room combiner, use the default key - SetupPanelDrivers(_propertiesConfig.DefaultRoomKey); - } - }); } - void roomCombiner_RoomCombinationScenarioChanged(object sender, EventArgs e) - { - var roomCombiner = sender as IEssentialsRoomCombiner; - - DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); - } - - /// - /// Determines the room key to use based on the scenario - /// - /// - void DetermineRoomKeyFromScenario(IRoomCombinationScenario scenario) - { - string newRoomKey = null; - - if (scenario.UiMap.ContainsKey(Key)) - { - newRoomKey = scenario.UiMap[Key]; - } - else if (scenario.UiMap.ContainsKey(_propertiesConfig.DefaultRoomKey)) - { - newRoomKey = scenario.UiMap[_propertiesConfig.DefaultRoomKey]; - } - - SetupPanelDrivers(newRoomKey); - } - /// /// Sets up drivers and links them to the room specified /// /// key of room to link the drivers to - void SetupPanelDrivers(string roomKey) + protected override void SetupPanelDrivers(string roomKey) { // Clear out any existing actions Panel.ClearAllSigActions(); @@ -338,13 +179,7 @@ namespace PepperDash.Essentials driver.Show(); } - void HomePressed() - { - if (BacklightTransitionedOnTimer == null) - PanelDriver.BackButtonPressed(); - } - - void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) + protected override void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) { // If the sig is transitioning on, mark it in case it was home button that transitioned it var blOnSig = (Panel as TswFt5ButtonSystem).ExtenderSystemReservedSigs.BacklightOnFeedback; @@ -382,26 +217,6 @@ namespace PepperDash.Essentials act(value); } } - - void Panel_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args) - { - if (Debug.Level == 2) - Debug.Console(2, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue); - var uo = args.Sig.UserObject; - if (uo is Action) - (uo as Action)(args.Sig.BoolValue); - else if (uo is Action) - (uo as Action)(args.Sig.UShortValue); - else if (uo is Action) - (uo as Action)(args.Sig.StringValue); - } - - void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args) - { - var uo = args.Button.UserObject; - if(uo is Action) - (uo as Action)(args.Button.State == eButtonState.Pressed); - } } public class EssentialsTouchpanelControllerFactory : EssentialsDeviceFactory diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 9bf1f8ca..b2a3b363 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -366,6 +366,7 @@ + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs new file mode 100644 index 00000000..01409cf4 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs @@ -0,0 +1,270 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using PepperDash.Essentials.Core; +using Crestron.SimplSharpPro.DeviceSupport; +using PepperDash.Core; +using Crestron.SimplSharpPro.UI; +using Crestron.SimplSharp.CrestronIO; +using Crestron.SimplSharpPro; + +namespace PepperDash.Essentials.Core.UI +{ + public abstract class TouchpanelBase: EssentialsDevice, IHasBasicTriListWithSmartObject + { + protected CrestronTouchpanelPropertiesConfig _config; + public BasicTriListWithSmartObject Panel { get; private set; } + + /// + /// Constructor for pre-created Panel. This constructor attempts to load the SGD file from the provided SGD path and subscribes to the + /// `SigChange` event for the provided panel. + /// + /// Essentials Device Key + /// Essentials Device Name + /// Provided TSW Panel + /// Path to SGD file + protected TouchpanelBase(string key, string name, Tswx52ButtonVoiceControl tsw, string sgdPath) + :base(key, name) + { + Panel = tsw; + + //moving loading of SGD to preactivation action...should make creation quicker + AddPreActivationAction(() => { + if(!string.IsNullOrEmpty(sgdPath)) + { + Debug.Console(1, this, "Loading sgd file from {0}", sgdPath); + Panel.LoadSmartObjects(sgdPath); + return; + } + + Debug.Console(1, this, "No SGD file path defined"); + }); + + Panel.SigChange += Panel_SigChange; + } + + /// + /// Constructor for use with DGE panels. This constructor attempts to load the provided SGD file from the provided SGD path and subscribes to the + /// `SigChange` event for the provided DGE. + /// + /// Essentials Device Key + /// Essentials Device Name + /// Provided DGE + /// Path to SGD file + protected TouchpanelBase(string key, string name, Dge100 dge, string sgdPath):base(key, name) + { + Panel = dge; + + AddPreActivationAction(() => + { + if (!string.IsNullOrEmpty(sgdPath)) + { + Debug.Console(1, this, "Loading sgd file from {0}", sgdPath); + Panel.LoadSmartObjects(sgdPath); + return; + } + + Debug.Console(1, this, "No SGD file path defined"); + }); + + Panel.SigChange += Panel_SigChange; + } + + /// + /// Constructor for use with device Factory. A touch panel device will be created based on the provided IP-ID and the + /// type of the panel. The SGD File path can be specified using the config property, or a default one located in the program directory if none + /// is provided. + /// + /// Essentials Device Key + /// Essentials Device Name + /// Touchpanel Type to build + /// Touchpanel Configuration + /// IP-ID to use for touch panel + protected TouchpanelBase(string key, string name, string type, CrestronTouchpanelPropertiesConfig config, uint id) + :base(key, name) + { + var panel = GetPanelForType(type, id); + if(panel != null) + { + Panel = panel; + } + + if (Panel is TswFt5ButtonSystem) + { + var tsw = Panel as TswFt5ButtonSystem; + tsw.ExtenderSystemReservedSigs.Use(); + tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange + += ExtenderSystemReservedSigs_DeviceExtenderSigChange; + + tsw.ButtonStateChange += Tsw_ButtonStateChange; + } + + + AddPreActivationAction(() => { + if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success) + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Registration failed. Continuing, but panel may not function: {0}", Panel.RegistrationFailureReason); + + // Give up cleanly if SGD is not present. + var sgdName = Global.FilePathPrefix + "sgd" + Global.DirectorySeparator + _config.SgdFile; + if (!File.Exists(sgdName)) + { + Debug.Console(0, this, "Smart object file '{0}' not present in User folder. Looking for embedded file", sgdName); + + sgdName = Global.ApplicationDirectoryPathPrefix + Global.DirectorySeparator + "SGD" + Global.DirectorySeparator + config.SgdFile; + + if (!File.Exists(sgdName)) + { + Debug.Console(0, this, "Unable to find SGD file '{0}' in User sgd or application SGD folder. Exiting touchpanel load.", sgdName); + return; + } + } + }); + + AddPostActivationAction(() => + { + // Check for IEssentialsRoomCombiner in DeviceManager and if found, subscribe to its event + var roomCombiner = DeviceManager.AllDevices.FirstOrDefault((d) => d is IEssentialsRoomCombiner) as IEssentialsRoomCombiner; + + if (roomCombiner != null) + { + // Subscribe to the even + roomCombiner.RoomCombinationScenarioChanged += new EventHandler(roomCombiner_RoomCombinationScenarioChanged); + + // Connect to the initial roomKey + if (roomCombiner.CurrentScenario != null) + { + // Use the current scenario + DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); + } + else + { + // Current Scenario not yet set. Use default + SetupPanelDrivers(_config.DefaultRoomKey); + } + } + else + { + // No room combiner, use the default key + SetupPanelDrivers(_config.DefaultRoomKey); + } + }); + } + + /// + /// Setup Panel operation + /// + /// Room Key for this panel + protected abstract void SetupPanelDrivers(string roomKey); + + + /// + /// + /// + /// + /// + protected virtual void roomCombiner_RoomCombinationScenarioChanged(object sender, EventArgs e) + { + var roomCombiner = sender as IEssentialsRoomCombiner; + + DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); + } + + /// + /// Determines the room key to use based on the scenario + /// + /// + protected virtual void DetermineRoomKeyFromScenario(IRoomCombinationScenario scenario) + { + string newRoomKey = null; + + if (scenario.UiMap.ContainsKey(Key)) + { + newRoomKey = scenario.UiMap[Key]; + } + else if (scenario.UiMap.ContainsKey(_config.DefaultRoomKey)) + { + newRoomKey = scenario.UiMap[_config.DefaultRoomKey]; + } + + SetupPanelDrivers(newRoomKey); + } + + private BasicTriListWithSmartObject GetPanelForType(string type, uint id) + { + type = type.ToLower(); + try + { + if (type == "crestronapp") + { + var app = new CrestronApp(id, Global.ControlSystem); + app.ParameterProjectName.Value = _config.ProjectName; + return app; + } + else if (type == "xpanel") + return new XpanelForSmartGraphics(id, Global.ControlSystem); + else if (type == "tsw550") + return new Tsw550(id, Global.ControlSystem); + else if (type == "tsw552") + return new Tsw552(id, Global.ControlSystem); + else if (type == "tsw560") + return new Tsw560(id, Global.ControlSystem); + else if (type == "tsw750") + return new Tsw750(id, Global.ControlSystem); + else if (type == "tsw752") + return new Tsw752(id, Global.ControlSystem); + else if (type == "tsw760") + return new Tsw760(id, Global.ControlSystem); + else if (type == "tsw1050") + return new Tsw1050(id, Global.ControlSystem); + else if (type == "tsw1052") + return new Tsw1052(id, Global.ControlSystem); + else if (type == "tsw1060") + return new Tsw1060(id, Global.ControlSystem); + else if (type == "tsw570") + return new Tsw570(id, Global.ControlSystem); + else if (type == "tsw770") + return new Tsw770(id, Global.ControlSystem); + else if (type == "ts770") + return new Ts770(id, Global.ControlSystem); + else if (type == "tsw1070") + return new Tsw1070(id, Global.ControlSystem); + else if (type == "ts1070") + return new Ts1070(id, Global.ControlSystem); + else + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW controller with type '{0}'", type); + return null; + } + } + catch (Exception e) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message); + return null; + } + } + + private void Panel_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args) + { + if (Debug.Level == 2) + Debug.Console(2, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue); + var uo = args.Sig.UserObject; + if (uo is Action) + (uo as Action)(args.Sig.BoolValue); + else if (uo is Action) + (uo as Action)(args.Sig.UShortValue); + else if (uo is Action) + (uo as Action)(args.Sig.StringValue); + } + + private void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args) + { + var uo = args.Button.UserObject; + if(uo is Action) + (uo as Action)(args.Button.State == eButtonState.Pressed); + } + + protected abstract void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args); + } +} \ No newline at end of file From 88a16b577b46778606f88b183ef6eb667e3a9418 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 2 Sep 2022 14:35:06 -0600 Subject: [PATCH 117/202] refactor: update constructors for touchpanel controller and base class --- .../UI/EssentialsTouchpanelController.cs | 100 +++++++++++----- .../UI/TouchpanelBase.cs | 109 +----------------- 2 files changed, 77 insertions(+), 132 deletions(-) diff --git a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs index 24bc33db..34d5e11a 100644 --- a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs +++ b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs @@ -12,35 +12,21 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.PageManagers; using PepperDash.Essentials.Core.UI; +using Newtonsoft.Json; namespace PepperDash.Essentials { public class EssentialsTouchpanelController : TouchpanelBase - { - private CrestronTouchpanelPropertiesConfig _propertiesConfig; - - public BasicTriListWithSmartObject Panel { get; private set; } - + { public PanelDriverBase PanelDriver { get; private set; } CTimer BacklightTransitionedOnTimer; - public EssentialsTouchpanelController(string key, string name, Tswx52ButtonVoiceControl tsw, - string projectName, string sgdPath) - : base(key, name, tsw, sgdPath) - { - } - - public EssentialsTouchpanelController(string key, string name, Dge100 dge, string projectName, string sgdPath) - : base(key, name, dge, sgdPath) - { - } - /// /// Config constructor /// - public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id) - : base(key, name, type, props, id) + public EssentialsTouchpanelController(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config) + : base(key, name, panel, config) { } @@ -56,7 +42,7 @@ namespace PepperDash.Essentials Debug.Console(0, this, "Linking TP '{0}' to Room '{1}'", Key, roomKey); - var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, _propertiesConfig); + var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, _config); // Then the sub drivers // spin up different room drivers depending on room type @@ -65,15 +51,15 @@ namespace PepperDash.Essentials { // Screen Saver Driver - mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _propertiesConfig); + mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _config); // Header Driver Debug.Console(0, this, "Adding header driver"); - mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _propertiesConfig); + mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _config); // AV Driver Debug.Console(0, this, "Adding huddle space AV driver"); - var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, _propertiesConfig); + var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, _config); avDriver.DefaultRoomKey = roomKey; mainDriver.AvDriver = avDriver; avDriver.CurrentRoom = room as IEssentialsHuddleSpaceRoom; @@ -82,7 +68,7 @@ namespace PepperDash.Essentials if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0) { Debug.Console(0, this, "Adding environment driver"); - mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _propertiesConfig); + mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _config); mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment); } @@ -111,13 +97,13 @@ namespace PepperDash.Essentials Debug.Console(0, this, "Adding huddle space VTC AV driver"); // Screen Saver Driver - mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _propertiesConfig); + mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _config); // Header Driver - mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _propertiesConfig); + mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _config); // AV Driver - var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, _propertiesConfig); + var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, _config); var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(Panel, avDriver, (room as IEssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver); @@ -130,7 +116,7 @@ namespace PepperDash.Essentials if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0) { Debug.Console(0, this, "Adding environment driver"); - mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _propertiesConfig); + mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _config); mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment); } @@ -229,13 +215,69 @@ namespace PepperDash.Essentials public override EssentialsDevice BuildDevice(DeviceConfig dc) { var comm = CommFactory.GetControlPropertiesConfig(dc); - var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString()); + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + + var panel = GetPanelForType(dc.Type, comm.IpIdInt, props.ProjectName); Debug.Console(1, "Factory Attempting to create new EssentialsTouchpanelController"); - var panelController = new EssentialsTouchpanelController(dc.Key, dc.Name, dc.Type, props, comm.IpIdInt); + var panelController = new EssentialsTouchpanelController(dc.Key, dc.Name, panel, props); return panelController; } + + private BasicTriListWithSmartObject GetPanelForType(string type, uint id, string projectName) + { + type = type.ToLower(); + try + { + if (type == "crestronapp") + { + var app = new CrestronApp(id, Global.ControlSystem); + app.ParameterProjectName.Value = projectName; + return app; + } + else if (type == "xpanel") + return new XpanelForSmartGraphics(id, Global.ControlSystem); + else if (type == "tsw550") + return new Tsw550(id, Global.ControlSystem); + else if (type == "tsw552") + return new Tsw552(id, Global.ControlSystem); + else if (type == "tsw560") + return new Tsw560(id, Global.ControlSystem); + else if (type == "tsw750") + return new Tsw750(id, Global.ControlSystem); + else if (type == "tsw752") + return new Tsw752(id, Global.ControlSystem); + else if (type == "tsw760") + return new Tsw760(id, Global.ControlSystem); + else if (type == "tsw1050") + return new Tsw1050(id, Global.ControlSystem); + else if (type == "tsw1052") + return new Tsw1052(id, Global.ControlSystem); + else if (type == "tsw1060") + return new Tsw1060(id, Global.ControlSystem); + else if (type == "tsw570") + return new Tsw570(id, Global.ControlSystem); + else if (type == "tsw770") + return new Tsw770(id, Global.ControlSystem); + else if (type == "ts770") + return new Ts770(id, Global.ControlSystem); + else if (type == "tsw1070") + return new Tsw1070(id, Global.ControlSystem); + else if (type == "ts1070") + return new Ts1070(id, Global.ControlSystem); + else + { + Debug.Console(0, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW controller with type '{0}'", type); + return null; + } + } + catch (Exception e) + { + Debug.Console(0, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message); + return null; + } + } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs index 01409cf4..806431ec 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs @@ -28,49 +28,9 @@ namespace PepperDash.Essentials.Core.UI protected TouchpanelBase(string key, string name, Tswx52ButtonVoiceControl tsw, string sgdPath) :base(key, name) { - Panel = tsw; - //moving loading of SGD to preactivation action...should make creation quicker - AddPreActivationAction(() => { - if(!string.IsNullOrEmpty(sgdPath)) - { - Debug.Console(1, this, "Loading sgd file from {0}", sgdPath); - Panel.LoadSmartObjects(sgdPath); - return; - } - - Debug.Console(1, this, "No SGD file path defined"); - }); - - Panel.SigChange += Panel_SigChange; } - /// - /// Constructor for use with DGE panels. This constructor attempts to load the provided SGD file from the provided SGD path and subscribes to the - /// `SigChange` event for the provided DGE. - /// - /// Essentials Device Key - /// Essentials Device Name - /// Provided DGE - /// Path to SGD file - protected TouchpanelBase(string key, string name, Dge100 dge, string sgdPath):base(key, name) - { - Panel = dge; - - AddPreActivationAction(() => - { - if (!string.IsNullOrEmpty(sgdPath)) - { - Debug.Console(1, this, "Loading sgd file from {0}", sgdPath); - Panel.LoadSmartObjects(sgdPath); - return; - } - - Debug.Console(1, this, "No SGD file path defined"); - }); - - Panel.SigChange += Panel_SigChange; - } /// /// Constructor for use with device Factory. A touch panel device will be created based on the provided IP-ID and the @@ -82,14 +42,10 @@ namespace PepperDash.Essentials.Core.UI /// Touchpanel Type to build /// Touchpanel Configuration /// IP-ID to use for touch panel - protected TouchpanelBase(string key, string name, string type, CrestronTouchpanelPropertiesConfig config, uint id) + protected TouchpanelBase(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config) :base(key, name) - { - var panel = GetPanelForType(type, id); - if(panel != null) - { - Panel = panel; - } + { + Panel = panel; if (Panel is TswFt5ButtonSystem) { @@ -100,7 +56,8 @@ namespace PepperDash.Essentials.Core.UI tsw.ButtonStateChange += Tsw_ButtonStateChange; } - + + _config = config; AddPreActivationAction(() => { if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success) @@ -112,7 +69,7 @@ namespace PepperDash.Essentials.Core.UI { Debug.Console(0, this, "Smart object file '{0}' not present in User folder. Looking for embedded file", sgdName); - sgdName = Global.ApplicationDirectoryPathPrefix + Global.DirectorySeparator + "SGD" + Global.DirectorySeparator + config.SgdFile; + sgdName = Global.ApplicationDirectoryPathPrefix + Global.DirectorySeparator + "SGD" + Global.DirectorySeparator + _config.SgdFile; if (!File.Exists(sgdName)) { @@ -191,60 +148,6 @@ namespace PepperDash.Essentials.Core.UI SetupPanelDrivers(newRoomKey); } - private BasicTriListWithSmartObject GetPanelForType(string type, uint id) - { - type = type.ToLower(); - try - { - if (type == "crestronapp") - { - var app = new CrestronApp(id, Global.ControlSystem); - app.ParameterProjectName.Value = _config.ProjectName; - return app; - } - else if (type == "xpanel") - return new XpanelForSmartGraphics(id, Global.ControlSystem); - else if (type == "tsw550") - return new Tsw550(id, Global.ControlSystem); - else if (type == "tsw552") - return new Tsw552(id, Global.ControlSystem); - else if (type == "tsw560") - return new Tsw560(id, Global.ControlSystem); - else if (type == "tsw750") - return new Tsw750(id, Global.ControlSystem); - else if (type == "tsw752") - return new Tsw752(id, Global.ControlSystem); - else if (type == "tsw760") - return new Tsw760(id, Global.ControlSystem); - else if (type == "tsw1050") - return new Tsw1050(id, Global.ControlSystem); - else if (type == "tsw1052") - return new Tsw1052(id, Global.ControlSystem); - else if (type == "tsw1060") - return new Tsw1060(id, Global.ControlSystem); - else if (type == "tsw570") - return new Tsw570(id, Global.ControlSystem); - else if (type == "tsw770") - return new Tsw770(id, Global.ControlSystem); - else if (type == "ts770") - return new Ts770(id, Global.ControlSystem); - else if (type == "tsw1070") - return new Tsw1070(id, Global.ControlSystem); - else if (type == "ts1070") - return new Ts1070(id, Global.ControlSystem); - else - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW controller with type '{0}'", type); - return null; - } - } - catch (Exception e) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message); - return null; - } - } - private void Panel_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args) { if (Debug.Level == 2) From 1b9f16ea744874eea21a2e9fc0ef3a590cc492f1 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 2 Sep 2022 14:44:15 -0600 Subject: [PATCH 118/202] fix: add missing event registration --- .../UI/TouchpanelBase.cs | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs index 806431ec..fbb7cd32 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs @@ -17,21 +17,6 @@ namespace PepperDash.Essentials.Core.UI protected CrestronTouchpanelPropertiesConfig _config; public BasicTriListWithSmartObject Panel { get; private set; } - /// - /// Constructor for pre-created Panel. This constructor attempts to load the SGD file from the provided SGD path and subscribes to the - /// `SigChange` event for the provided panel. - /// - /// Essentials Device Key - /// Essentials Device Name - /// Provided TSW Panel - /// Path to SGD file - protected TouchpanelBase(string key, string name, Tswx52ButtonVoiceControl tsw, string sgdPath) - :base(key, name) - { - - } - - /// /// Constructor for use with device Factory. A touch panel device will be created based on the provided IP-ID and the /// type of the panel. The SGD File path can be specified using the config property, or a default one located in the program directory if none @@ -45,7 +30,9 @@ namespace PepperDash.Essentials.Core.UI protected TouchpanelBase(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config) :base(key, name) { - Panel = panel; + Panel = panel; + + Panel.SigChange += Panel_SigChange; if (Panel is TswFt5ButtonSystem) { @@ -116,6 +103,14 @@ namespace PepperDash.Essentials.Core.UI protected abstract void SetupPanelDrivers(string roomKey); + /// + /// Event handler for System Extender Events + /// + /// + /// + protected abstract void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args); + + /// /// /// @@ -167,7 +162,5 @@ namespace PepperDash.Essentials.Core.UI if(uo is Action) (uo as Action)(args.Button.State == eButtonState.Pressed); } - - protected abstract void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args); } } \ No newline at end of file From 9b2611be02040b1f4c7e6a02e96b12e94e056b23 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 2 Sep 2022 15:00:00 -0600 Subject: [PATCH 119/202] refactor: add error handling for cases where type isn't found --- .../UI/EssentialsTouchpanelController.cs | 5 +++++ .../PepperDashEssentialsBase/UI/TouchpanelBase.cs | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs index 34d5e11a..67f25f42 100644 --- a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs +++ b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs @@ -219,6 +219,11 @@ namespace PepperDash.Essentials var panel = GetPanelForType(dc.Type, comm.IpIdInt, props.ProjectName); + if (panel == null) + { + Debug.Console(0, "Unable to create Touchpanel for type {0}. Touchpanel Controller WILL NOT function correctly", dc.Type); + } + Debug.Console(1, "Factory Attempting to create new EssentialsTouchpanelController"); var panelController = new EssentialsTouchpanelController(dc.Key, dc.Name, panel, props); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs index fbb7cd32..36e0342e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs @@ -29,7 +29,14 @@ namespace PepperDash.Essentials.Core.UI /// IP-ID to use for touch panel protected TouchpanelBase(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config) :base(key, name) - { + { + + if (Panel == null) + { + Debug.Console(0, this, "Panel is not valid. Touchpanel class WILL NOT work correctly"); + return; + } + Panel = panel; Panel.SigChange += Panel_SigChange; From f1d1ce9722f56146d9a5f1961b07fd1381119466 Mon Sep 17 00:00:00 2001 From: jdevito Date: Tue, 6 Sep 2022 14:04:19 -0500 Subject: [PATCH 120/202] fix: added OnPasswordRequired event call in SubmitPassword method to clear popup when bridged --- .../Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 32415d1d..21048d56 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -3357,6 +3357,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { Debug.Console(2, this, "Password Submitted: {0}", password); Dial(_lastDialedMeetingNumber, password); + OnPasswordRequired(false, false, true, ""); } void OnPasswordRequired(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) From f1590aeec8772920cb5d0d8195817e9226472bfa Mon Sep 17 00:00:00 2001 From: jdevito Date: Tue, 6 Sep 2022 14:10:21 -0500 Subject: [PATCH 121/202] fix: added 'CancelPasswordPrompt' join, updated linkToZoomApi --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 2 ++ .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 21048d56..8de58c23 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2495,6 +2495,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom trilist.SetStringSigAction(joinMap.SubmitPassword.JoinNumber, SubmitPassword); + trilist.SetStringSigAction(joinMap.CancelPasswordPrompt.JoinNumber, + delegate { OnPasswordRequired(false, false, true, ""); }); PasswordRequired += (devices, args) => { if (args.LoginAttemptCancelled) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs index 48b2c039..b0b497de 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs @@ -23,6 +23,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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 [JoinName("PasswordIncorrect")] public JoinDataComplete PasswordIncorrect = new JoinDataComplete( From ccf7acd53d0da7b8d4ade184f352a6b52d4f418a Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Tue, 6 Sep 2022 17:16:27 -0500 Subject: [PATCH 122/202] feat: update bridging, device factory, and interfaces In order to support the way some Smart Objects work, a clear directory join was needed in order to allow for clearing a selection in certain circumstances. In order to support finer-grained dependencies while developing plugins, the Development Device Factory was added. --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 35 +- .../Devices/EssentialsDevice.cs | 11 + .../Extensions/StringExtensions.cs | 20 + .../PepperDashEssentialsBase/Global/Global.cs | 33 ++ .../PepperDash_Essentials_Core.csproj | 1 + .../Plugins/IPluginDeviceFactory.cs | 8 +- .../Plugins/PluginLoader.cs | 6 +- .../Codec/iHasDirectory.cs | 1 + .../Codec/iHasScheduleAwareness.cs | 14 +- .../Essentials Devices Common.csproj | 2 +- .../CiscoCodec/BookingsDataClasses.cs | 65 ++++ .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 10 +- .../VideoCodec/CiscoCodec/RoomPresets.cs | 4 +- .../VideoCodec/CiscoCodec/xStatus.cs | 8 +- ...vertiblePreset.cs => ConvertiblePreset.cs} | 4 +- .../VideoCodec/Interfaces/IHasCodecLayouts.cs | 19 - .../VideoCodec/VideoCodecBase.cs | 348 +++++++++--------- 17 files changed, 381 insertions(+), 208 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs rename essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/{IConvertiblePreset.cs => ConvertiblePreset.cs} (54%) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 9e982700..943ecc20 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -398,6 +398,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("DirectoryEntryIsContact")] public JoinDataComplete DirectoryEntryIsContact = new JoinDataComplete( new JoinData @@ -524,6 +525,21 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("DirectoryClearSelected")] + public JoinDataComplete DirectoryClearSelected = new JoinDataComplete( + new JoinData + { + JoinNumber = 110, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Clear Selected Entry and String from Search", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraTiltUp")] public JoinDataComplete CameraTiltUp = new JoinDataComplete( new JoinData @@ -1256,11 +1272,12 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps }, new JoinMetadata { - Description = "Directory Select Row", + Description = "Directory Select Row and Feedback", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("SelectedContactMethodCount")] public JoinDataComplete SelectedContactMethodCount = new JoinDataComplete( new JoinData @@ -1289,6 +1306,22 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Analog }); + [JoinName("DirectorySelectRowFeedback")] + public JoinDataComplete DirectorySelectRowFeedback = new JoinDataComplete( + new JoinData + { + JoinNumber = 104, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Select Row and Feedback", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + + [JoinName("CameraPresetSelect")] public JoinDataComplete CameraPresetSelect = new JoinDataComplete( new JoinData diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs index a72bd282..a3ca94f3 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs @@ -131,4 +131,15 @@ namespace PepperDash.Essentials.Core /// public string MinimumEssentialsFrameworkVersion { get; protected set; } } + + public abstract class EssentialsPluginDevelopmentDeviceFactory : EssentialsDeviceFactory, IPluginDevelopmentDeviceFactory where T : EssentialsDevice + { + /// + /// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33") + /// + public string MinimumEssentialsFrameworkVersion { get; protected set; } + + public List DevelopmentEssentialsFrameworkVersions { get; protected set; } + } + } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs new file mode 100644 index 00000000..708ed930 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Essentials.Core +{ + public static class StringExtensions + { + public static string NullIfEmpty(this string s) + { + return string.IsNullOrEmpty(s) ? null : s; + } + public static string NullIfWhiteSpace(this string s) + { + return string.IsNullOrEmpty(s.Trim()) ? null : s; + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs index 2bafc2ae..09529ff8 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Text.RegularExpressions; using System.Globalization; using Crestron.SimplSharp; @@ -162,6 +163,38 @@ namespace PepperDash.Essentials.Core AssemblyVersion = assemblyVersion; } + public static bool IsRunningDevelopmentVersion(List developmentVersions, string minimumVersion) + { + if (Regex.Match(AssemblyVersion, @"^(\d*).(\d*).(\d*).*").Groups[1].Value == "0") + { + Debug.Console(2, "Running Local Build. Bypassing Dependency Check."); + return true; + } + + if (developmentVersions == null) + { + Debug.Console(0, + "Development Plugin does not specify a list of versions. Loading plugin may not work as expected. Checking Minumum version"); + return IsRunningMinimumVersionOrHigher(minimumVersion); + } + + Debug.Console(2, "Comparing running version '{0}' to minimum versions '{1}'", AssemblyVersion, developmentVersions); + + var versionMatch = developmentVersions.FirstOrDefault(x => x == AssemblyVersion); + + if (String.IsNullOrEmpty(versionMatch)) + { + Debug.Console(0, "Essentials Build does not match any builds required for plugin load. Bypassing Plugin Load."); + return false; + } + + Debug.Console(2, "Essentials Build {0} matches list of development builds", AssemblyVersion); + return IsRunningMinimumVersionOrHigher(minimumVersion); + + + + } + /// /// Checks to see if the running version meets or exceed the minimum specified version. For beta versions (0.xx.yy), will always return true. /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index b2a3b363..dfa59b88 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -218,6 +218,7 @@ + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Plugins/IPluginDeviceFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Plugins/IPluginDeviceFactory.cs index ff979599..ec823007 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Plugins/IPluginDeviceFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Plugins/IPluginDeviceFactory.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using PepperDash.Core; @@ -15,5 +16,10 @@ namespace PepperDash.Essentials.Core } + public interface IPluginDevelopmentDeviceFactory : IPluginDeviceFactory + { + List DevelopmentEssentialsFrameworkVersions { get; } + } +} + -} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Plugins/PluginLoader.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Plugins/PluginLoader.cs index 136303e3..9da843b8 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Plugins/PluginLoader.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Plugins/PluginLoader.cs @@ -425,7 +425,11 @@ namespace PepperDash.Essentials /// static void LoadCustomPlugin(IPluginDeviceFactory plugin, LoadedAssembly loadedAssembly) { - var passed = Global.IsRunningMinimumVersionOrHigher(plugin.MinimumEssentialsFrameworkVersion); + var developmentPlugin = plugin as IPluginDevelopmentDeviceFactory; + + var passed = developmentPlugin != null ? Global.IsRunningDevelopmentVersion + (developmentPlugin.DevelopmentEssentialsFrameworkVersions, developmentPlugin.MinimumEssentialsFrameworkVersion) + : Global.IsRunningMinimumVersionOrHigher(plugin.MinimumEssentialsFrameworkVersion); if (!passed) { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs index 57dbbd6b..93eda176 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs @@ -49,6 +49,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec Stack DirectoryBrowseHistoryStack { get; } } + /// /// /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs index 06edf7bf..9169fd7c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs @@ -211,7 +211,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec get { var joinable = StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now - && DateTime.Now <= EndTime.AddMinutes(-5); + && DateTime.Now <= EndTime.AddSeconds(-_joinableCooldownSeconds); //Debug.Console(2, "Meeting Id: {0} joinable: {1}", Id, joinable); return joinable; } @@ -231,11 +231,23 @@ namespace PepperDash.Essentials.Devices.Common.Codec [JsonIgnore] public eMeetingEventChangeType NotifiedChangeTypes { get; set; } + [JsonIgnore] private readonly int _joinableCooldownSeconds; + + public Meeting() { Calls = new List(); + _joinableCooldownSeconds = 300; } + public Meeting(int joinableCooldownSeconds) + { + Calls = new List(); + _joinableCooldownSeconds = joinableCooldownSeconds; + } + + + #region Overrides of Object public override string ToString() diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index 547e8711..af6ab740 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -108,7 +108,7 @@ - + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs index cf4d8530..59823bb9 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs @@ -377,5 +377,70 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec return meetings; } + + public static List GetGenericMeetingsFromBookingResult(List bookings, int joinableCooldownSeconds) + { + var meetings = new List(); + + if (Debug.Level > 0) + { + Debug.Console(1, "Meetings List:\n"); + } + + foreach (Booking b in bookings) + { + var meeting = new Meeting(joinableCooldownSeconds); + + if (b.Id != null) + meeting.Id = b.Id.Value; + if (b.Organizer != null) + meeting.Organizer = string.Format("{0}, {1}", b.Organizer.LastName.Value, b.Organizer.FirstName.Value); + if (b.Title != null) + meeting.Title = b.Title.Value; + if (b.Agenda != null) + meeting.Agenda = b.Agenda.Value; + if (b.Time != null) + { + meeting.StartTime = b.Time.StartTime.Value; + meeting.EndTime = b.Time.EndTime.Value; + } + if (b.Privacy != null) + meeting.Privacy = CodecCallPrivacy.ConvertToDirectionEnum(b.Privacy.Value); + + //#warning Update this ConnectMode conversion after testing onsite. Expected value is "OBTP", but in PD NYC Test scenarios, "Manual" is being returned for OBTP meetings + if (b.DialInfo.ConnectMode != null) + if (b.DialInfo.ConnectMode.Value.ToLower() == "obtp" || b.DialInfo.ConnectMode.Value.ToLower() == "manual") + meeting.IsOneButtonToPushMeeting = true; + + if (b.DialInfo.Calls.Call != null) + { + foreach (Call c in b.DialInfo.Calls.Call) + { + meeting.Calls.Add(new PepperDash.Essentials.Devices.Common.Codec.Call() + { + Number = c.Number.Value, + Protocol = c.Protocol.Value, + CallRate = c.CallRate.Value, + CallType = c.CallType.Value + }); + } + } + + + meetings.Add(meeting); + + if (Debug.Level > 0) + { + Debug.Console(1, "Title: {0}, ID: {1}, Organizer: {2}, Agenda: {3}", meeting.Title, meeting.Id, meeting.Organizer, meeting.Agenda); + Debug.Console(1, " Start Time: {0}, End Time: {1}, Duration: {2}", meeting.StartTime, meeting.EndTime, meeting.Duration); + Debug.Console(1, " Joinable: {0}\n", meeting.Joinable); + } + } + + meetings.OrderBy(m => m.StartTime); + + return meetings; + } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 0bca7181..7dcf40bb 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -24,7 +24,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { enum eCommandType { SessionStart, SessionEnd, Command, GetStatus, GetConfiguration }; public enum eExternalSourceType {camera, desktop, document_camera, mediaplayer, PC, whiteboard, other} - public enum eExternalSourceMode {Ready, NotReady, Hidden, Error} + public enum eExternalSourceMode {Ready, NotReady, Hidden, Error} public class CiscoSparkCodec : VideoCodecBase, IHasCallHistory, IHasCallFavorites, IHasDirectory, IHasScheduleAwareness, IOccupancyStatusProvider, IHasCodecLayouts, IHasCodecSelfView, @@ -1023,7 +1023,7 @@ ConnectorID: {2}" if (tempPresets.Count > 0) { // Create temporary list to store the existing items from the CiscoCodecStatus.RoomPreset collection - var existingRoomPresets = new List(); + var existingRoomPresets = new List(); // Add the existing items to the temporary list existingRoomPresets.AddRange(CodecStatus.Status.RoomPreset); // Populate the CodecStatus object (this will append new values to the RoomPreset collection @@ -1031,8 +1031,6 @@ ConnectorID: {2}" var jResponse = JObject.Parse(response); - List convertedRoomPresets = - existingRoomPresets.Select(a => (CiscoCodecStatus.RoomPreset) a).ToList(); IList roomPresets = jResponse["Status"]["RoomPreset"].Children().ToList(); // Iterate the new items in this response agains the temporary list. Overwrite any existing items and add new ones. @@ -1041,7 +1039,7 @@ ConnectorID: {2}" var preset = camPreset as CiscoCodecStatus.RoomPreset; if (preset == null) continue; // First fine the existing preset that matches the id - var existingPreset = convertedRoomPresets.FirstOrDefault(p => p.id.Equals(preset.id)); + var existingPreset = existingRoomPresets.FirstOrDefault(p => p.id.Equals(preset.id)); if (existingPreset != null) { Debug.Console(1, this, "Existing Room Preset with ID: {0} found. Updating.", existingPreset.id); @@ -1073,7 +1071,7 @@ ConnectorID: {2}" CodecStatus.Status.RoomPreset = existingRoomPresets; // Generecise the list - NearEndPresets = existingRoomPresets.GetGenericPresets(); + NearEndPresets = existingRoomPresets.GetGenericPresets(); var handler = CodecRoomPresetsListHasChanged; if (handler != null) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs index 4fec0d89..8fc8a1d0 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/RoomPresets.cs @@ -32,12 +32,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// /// /// - public static List GetGenericPresets(this List presets) + public static List GetGenericPresets(this List presets) where TSource : ConvertiblePreset where TDestination : PresetBase { return presets.Select(preset => preset.ConvertCodecPreset()) .Where(newPreset => newPreset != null) - .Cast() + .Cast() .ToList(); } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs index 23e8c6ab..2d8e903a 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs @@ -2186,7 +2186,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } } - public class RoomPreset : IConvertiblePreset + public class RoomPreset : ConvertiblePreset { public string id { get; set; } public Defined Defined { get; set; } @@ -2200,7 +2200,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco Type = new Type5(); } - public PresetBase ConvertCodecPreset() + public override PresetBase ConvertCodecPreset() { try { @@ -2240,7 +2240,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public Proximity Proximity { get; set; } public RoomAnalytics RoomAnalytics { get; set; } - public List RoomPreset { get; set; } + public List RoomPreset { get; set; } public SIP SIP { get; set; } public Security Security { get; set; } @@ -2257,7 +2257,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco Standby = new Standby(); Cameras = new Cameras(); RoomAnalytics = new RoomAnalytics(); - RoomPreset = new List(); + RoomPreset = new List(); Conference = new Conference2(); SystemUnit = new SystemUnit(); Video = new Video(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ConvertiblePreset.cs similarity index 54% rename from essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs rename to essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ConvertiblePreset.cs index f6f3f74f..4c01d94e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/IConvertiblePreset.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ConvertiblePreset.cs @@ -2,8 +2,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { - public interface IConvertiblePreset + public abstract class ConvertiblePreset { - PresetBase ConvertCodecPreset(); + public abstract PresetBase ConvertCodecPreset(); } } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs index bfc43db6..44a482e1 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasCodecLayouts.cs @@ -22,25 +22,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec void MinMaxLayoutToggle(); } - /// - /// Defines the required elements for layout control with direct layout selection - /// - public interface IHasCodecLayoutsAvailable : IHasCodecLayouts - { - - event EventHandler AvailableLayoutsChanged; - - StringFeedback AvailableLocalLayoutsFeedback { get; } - List AvailableLocalLayouts { get; } - void LocalLayoutSet(string layout); - void LocalLayoutSet(CodecCommandWithLabel layout); - - } - - public class AvailableLayoutChangedEventArgs : EventArgs - { - public List AvailableLayouts { get; set; } - } /// /// Defines the requirements for Zoom Room layout control diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index bf7fe188..e86751d3 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -11,6 +11,7 @@ using PepperDash.Core; using PepperDash.Core.Intersystem; using PepperDash.Core.Intersystem.Tokens; using PepperDash.Core.WebApi.Presets; +using Crestron.SimplSharp.Reflection; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; @@ -31,6 +32,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec private const int XSigEncoding = 28591; protected const int MaxParticipants = 50; private readonly byte[] _clearBytes = XSigHelpers.ClearOutputs(); + + private IHasDirectory _directoryCodec; + private BasicTriList _directoryTrilist; + private VideoCodecControllerJoinMap _directoryJoinmap; + + protected string _timeFormatSpecifier; + protected string _dateFormatSpecifier; + + protected VideoCodecBase(DeviceConfig config) : base(config) { @@ -371,10 +381,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecCameraLayoutsToApi(codec as IHasCodecLayouts, trilist, joinMap); } - if (codec is IHasCodecLayoutsAvailable) - { - LinkVideoCodecAvailableLayoutsToApi(codec as IHasCodecLayoutsAvailable, trilist, joinMap); - } if (codec is IHasSelfviewPosition) { @@ -692,37 +698,37 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (meetingIndex >= maxParticipants * offset) break; -// Debug.Console(2, this, -//@"Updating Participant on xsig: -//Name: {0} (s{9}) -//AudioMute: {1} (d{10}) -//VideoMute: {2} (d{11}) -//CanMuteVideo: {3} (d{12}) -//CanUMuteVideo: {4} (d{13}) -//IsHost: {5} (d{14}) -//HandIsRaised: {6} (d{15}) -//IsPinned: {7} (d{16}) -//ScreenIndexIsPinnedTo: {8} (a{17}) -//", -// participant.Name, -// participant.AudioMuteFb, -// participant.VideoMuteFb, -// participant.CanMuteVideo, -// participant.CanUnmuteVideo, -// participant.IsHost, -// participant.HandIsRaisedFb, -// participant.IsPinnedFb, -// participant.ScreenIndexIsPinnedToFb, -// stringIndex + 1, -// digitalIndex + 1, -// digitalIndex + 2, -// digitalIndex + 3, -// digitalIndex + 4, -// digitalIndex + 5, -// digitalIndex + 6, -// digitalIndex + 7, -// analogIndex + 1 -// ); + // Debug.Console(2, this, + //@"Updating Participant on xsig: + //Name: {0} (s{9}) + //AudioMute: {1} (d{10}) + //VideoMute: {2} (d{11}) + //CanMuteVideo: {3} (d{12}) + //CanUMuteVideo: {4} (d{13}) + //IsHost: {5} (d{14}) + //HandIsRaised: {6} (d{15}) + //IsPinned: {7} (d{16}) + //ScreenIndexIsPinnedTo: {8} (a{17}) + //", + // participant.Name, + // participant.AudioMuteFb, + // participant.VideoMuteFb, + // participant.CanMuteVideo, + // participant.CanUnmuteVideo, + // participant.IsHost, + // participant.HandIsRaisedFb, + // participant.IsPinnedFb, + // participant.ScreenIndexIsPinnedToFb, + // stringIndex + 1, + // digitalIndex + 1, + // digitalIndex + 2, + // digitalIndex + 3, + // digitalIndex + 4, + // digitalIndex + 5, + // digitalIndex + 6, + // digitalIndex + 7, + // analogIndex + 1 + // ); //digitals @@ -789,10 +795,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetSigFalseAction(joinMap.SourceShareStart.JoinNumber, StartSharing); trilist.SetSigFalseAction(joinMap.SourceShareEnd.JoinNumber, StopSharing); - trilist.SetBoolSigAction(joinMap.SourceShareAutoStart.JoinNumber, (b) => AutoShareContentWhileInCall = b); + trilist.SetBoolSigAction(joinMap.SourceShareAutoStart.JoinNumber, b => AutoShareContentWhileInCall = b); } - private List _currentMeetings = new List(); + private List _currentMeetings = new List(); private void LinkVideoCodecScheduleToApi(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { @@ -800,7 +806,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetUShortSigAction(joinMap.MinutesBeforeMeetingStart.JoinNumber, (i) => { - codec.CodecSchedule.MeetingWarningMinutes = i; + codec.CodecSchedule.MeetingWarningMinutes = i; }); trilist.SetSigFalseAction(joinMap.DialMeeting1.JoinNumber, () => @@ -904,90 +910,90 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set public IntFeedback MeetingsToDisplayFeedback { get; set; } - private string UpdateMeetingsListXSig(List meetings) - { + private string UpdateMeetingsListXSig(List meetings) + { // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set //const int _meetingsToDisplay = 3; - const int maxDigitals = 2; - const int maxStrings = 7; - const int offset = maxDigitals + maxStrings; - var digitalIndex = maxStrings * _meetingsToDisplay; //15 - var stringIndex = 0; - var meetingIndex = 0; + const int maxDigitals = 2; + const int maxStrings = 7; + const int offset = maxDigitals + maxStrings; + var digitalIndex = maxStrings * _meetingsToDisplay; //15 + var stringIndex = 0; + var meetingIndex = 0; - var tokenArray = new XSigToken[_meetingsToDisplay * offset]; - /* - * Digitals - * IsJoinable - 1 - * IsDialable - 2 - * - * Serials - * Organizer - 1 - * Title - 2 - * Start Date - 3 - * Start Time - 4 - * End Date - 5 - * End Time - 6 - * Id - 7 - */ + var tokenArray = new XSigToken[_meetingsToDisplay * offset]; + /* + * Digitals + * IsJoinable - 1 + * IsDialable - 2 + * + * Serials + * Organizer - 1 + * Title - 2 + * Start Date - 3 + * Start Time - 4 + * End Date - 5 + * End Time - 6 + * Id - 7 + */ + + foreach (var meeting in meetings) + { + var currentTime = DateTime.Now; - foreach (var meeting in meetings) - { - var currentTime = DateTime.Now; + if (meeting.StartTime < currentTime && meeting.EndTime < currentTime) continue; - if (meeting.StartTime < currentTime && meeting.EndTime < currentTime) continue; + if (meetingIndex >= _meetingsToDisplay * offset) + { + Debug.Console(2, this, "Max Meetings reached"); + break; + } - if (meetingIndex >= _meetingsToDisplay * offset) - { - Debug.Console(2, this, "Max Meetings reached"); - break; - } + //digitals + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, meeting.Joinable); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, meeting.Id != "0"); - //digitals - tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, meeting.Joinable); - tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, meeting.Id != "0"); + //serials + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, meeting.Title); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToString(_dateFormatSpecifier.NullIfEmpty() ?? "d", Global.Culture)); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.StartTime.ToString(_timeFormatSpecifier.NullIfEmpty() ?? "t", Global.Culture)); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToString(_dateFormatSpecifier.NullIfEmpty() ?? "d", Global.Culture)); + tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToString(_timeFormatSpecifier.NullIfEmpty() ?? "t", Global.Culture)); + tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, meeting.Id); - //serials - tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer); - tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, meeting.Title); - tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToString("t", Global.Culture)); - tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.StartTime.ToString("t", Global.Culture)); - tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToString("t", Global.Culture)); - tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToString("t", Global.Culture)); - tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, meeting.Id); + digitalIndex += maxDigitals; + meetingIndex += offset; + stringIndex += maxStrings; + } + while (meetingIndex < _meetingsToDisplay * offset) + { + Debug.Console(2, this, "Clearing unused data. Meeting Index: {0} MaxMeetings * Offset: {1}", + meetingIndex, _meetingsToDisplay * offset); - digitalIndex += maxDigitals; - meetingIndex += offset; - stringIndex += maxStrings; - } + //digitals + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); - while (meetingIndex < _meetingsToDisplay * offset) - { - Debug.Console(2, this, "Clearing unused data. Meeting Index: {0} MaxMeetings * Offset: {1}", - meetingIndex, _meetingsToDisplay * offset); + //serials + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); + tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); + tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, String.Empty); - //digitals - tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); - tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); + digitalIndex += maxDigitals; + meetingIndex += offset; + stringIndex += maxStrings; + } - //serials - tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); - tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); - tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); - tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); - tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); - tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); - tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, String.Empty); + return GetXSigString(tokenArray); + } - digitalIndex += maxDigitals; - meetingIndex += offset; - stringIndex += maxStrings; - } - - return GetXSigString(tokenArray); - } private void LinkVideoCodecDirectoryToApi(IHasDirectory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { @@ -998,7 +1004,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i, trilist, joinMap)); - // Report feedback for number of contact methods for selected contact + //Special Change for protected directory clear + + trilist.SetBoolSigAction(joinMap.DirectoryClearSelected.JoinNumber, (b) => SelectDirectoryEntry(_directoryCodec, 0, _directoryTrilist, _directoryJoinmap)); + + // Report feedback for number of contact methods for selected contact trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot); @@ -1012,7 +1022,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetString(joinMap.DirectoryEntries.JoinNumber, Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); + var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, + codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length); @@ -1027,32 +1038,32 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetString(joinMap.DirectoryEntries.JoinNumber, Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var directoryXSig = UpdateDirectoryXSig(args.Directory, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); - + var directoryXSig = UpdateDirectoryXSig(args.Directory, + codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length); trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); }; - + trilist.OnlineStatusChange += (device, args) => { if (!args.DeviceOnLine) return; - var clearBytes = XSigHelpers.ClearOutputs(); - trilist.SetString(joinMap.DirectoryEntries.JoinNumber, - Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); - trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); + var clearBytes = XSigHelpers.ClearOutputs(); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); }; } - - private void SelectDirectoryEntry(IHasDirectory codec, ushort i, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { - if (i < 1 || i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return; + if (i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return; + _selectedDirectoryItem = i == 0 ? null : codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1]; + trilist.SetUshort(joinMap.DirectorySelectRowFeedback.JoinNumber, i); - _selectedDirectoryItem = codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1]; + if (_selectedDirectoryItem == null) trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, false); if (_selectedDirectoryItem is DirectoryFolder) @@ -1064,6 +1075,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber); trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber); trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber); + trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, false); return; } @@ -1071,13 +1083,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, string.Empty); var selectedContact = _selectedDirectoryItem as DirectoryContact; - if (selectedContact != null) - { - trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, selectedContact.Name); - - } - // Allow auto dial of selected line. Always dials first contact method + if (selectedContact != null && selectedContact.ContactMethods.Count >= 1) + { + trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, true); + } + + trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, + selectedContact != null ? selectedContact.Name : string.Empty); + + // Allow auto dial of selected line. Always dials first contact method if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber)) { var invitableEntry = _selectedDirectoryItem as IInvitableContact; @@ -1090,12 +1105,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec var entryToDial = _selectedDirectoryItem as DirectoryContact; - trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber, selectedContact.ContactMethods[0].Number); + trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber, + selectedContact != null ? selectedContact.ContactMethods[0].Number : string.Empty); if (entryToDial == null) return; Dial(entryToDial.ContactMethods[0].Number); - return; } else { @@ -1181,50 +1196,49 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec return GetXSigString(tokenArray); } - private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot) - { - var xSigMaxIndex = 1023; - var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count > xSigMaxIndex - ? xSigMaxIndex - : directory.CurrentDirectoryResults.Count]; + private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot) + { + var xSigMaxIndex = 1023; + var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count > xSigMaxIndex + ? xSigMaxIndex + : directory.CurrentDirectoryResults.Count]; - Debug.Console(2, this, "IsRoot: {0}, Directory Count: {1}, TokenArray.Length: {2}", isRoot, directory.CurrentDirectoryResults.Count, tokenArray.Length); + Debug.Console(2, this, "IsRoot: {0}, Directory Count: {1}, TokenArray.Length: {2}", isRoot, + directory.CurrentDirectoryResults.Count, tokenArray.Length); - var contacts = directory.CurrentDirectoryResults.Count > xSigMaxIndex - ? directory.CurrentDirectoryResults.Take(xSigMaxIndex) - : directory.CurrentDirectoryResults; - - var contactsToDisplay = isRoot - ? contacts.Where(c => c.ParentFolderId == "root") - : contacts.Where(c => c.ParentFolderId != "root"); + var contacts = directory.CurrentDirectoryResults.Count > xSigMaxIndex + ? directory.CurrentDirectoryResults.Take(xSigMaxIndex) + : directory.CurrentDirectoryResults; - var counterIndex = 1; - foreach (var entry in contactsToDisplay) - { - var arrayIndex = counterIndex - 1; - var entryIndex = counterIndex; + var counterIndex = 1; + foreach (var entry in contacts) + { + var arrayIndex = counterIndex - 1; + var entryIndex = counterIndex; - 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); + Debug.Console(2, this, "Entry{2:0000} Name: {0}, Folder ID: {1}", entry.Name, entry.FolderId, entryIndex); - if (entry is DirectoryFolder) - { - tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, String.Format("[+] {0}", entry.Name)); + if (entry is DirectoryFolder && entry.ParentFolderId == "root") + { + tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, String.Format("[+] {0}", entry.Name)); - counterIndex++; + counterIndex++; + counterIndex++; - continue; - } + continue; + } + + tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, entry.Name); + + counterIndex++; + } + + return GetXSigString(tokenArray); - tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, entry.Name); - counterIndex++; - } - - return GetXSigString(tokenArray); } - private void LinkVideoCodecCallControlsToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + private void LinkVideoCodecCallControlsToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { trilist.SetSigFalseAction(joinMap.ManualDial.JoinNumber, () => Dial(trilist.StringOutput[joinMap.CurrentDialString.JoinNumber].StringValue)); @@ -1489,14 +1503,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentLayoutStringFb.JoinNumber]); } - private void LinkVideoCodecAvailableLayoutsToApi(IHasCodecLayoutsAvailable codec, BasicTriList trilist, - VideoCodecControllerJoinMap joinMap) - { - codec.AvailableLocalLayoutsFeedback.LinkInputSig(trilist.StringInput[joinMap.AvailableLayoutsFb.JoinNumber]); - - trilist.SetStringSigAction(joinMap.SelectLayout.JoinNumber, codec.LocalLayoutSet); - } - private void LinkVideoCodecCameraModeToApi(IHasCameraAutoMode codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { trilist.SetSigFalseAction(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeOn); @@ -2023,4 +2029,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } } + + } \ No newline at end of file From c557400f383b5c5450c856c5baef93e1c2fd4a69 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 26 Aug 2022 15:07:57 -0600 Subject: [PATCH 123/202] fix(essentials): updates ZoomRoom mute state to report muted when not in call --- .../VideoCodec/VideoCodecBase.cs | 2 ++ .../VideoCodec/ZoomRoom/ZoomRoom.cs | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 6e577c59..1270b690 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -214,6 +214,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec handler(this, new CodecCallStatusItemChangeEventArgs(item)); } + PrivacyModeIsOnFeedback.FireUpdate(); + if (AutoShareContentWhileInCall) { StartSharing(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 32415d1d..a8b413a8 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -214,7 +214,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom protected override Func PrivacyModeIsOnFeedbackFunc { - get { return () => Configuration.Call.Microphone.Mute; } + get + { + return () => + { + Debug.Console(2, this, "PrivacyModeIsOnFeedbackFunc. IsInCall: {0} muteState: {1}", IsInCall, Configuration.Call.Microphone.Mute); + if (IsInCall) + { + Debug.Console(2, this, "reporting muteState: ", Configuration.Call.Microphone.Mute); + return Configuration.Call.Microphone.Mute; + } + else + { + Debug.Console(2, this, "muteState: true", IsInCall); + return true; + } + }; + } } protected override Func StandbyIsOnFeedbackFunc From 215cf6696e379c15222a512d54d98c06e159857b Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 8 Sep 2022 14:22:53 -0600 Subject: [PATCH 124/202] fix(essentials): Set not in call state to report as unmuted --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index a8b413a8..d3c0cd0f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -218,16 +218,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { return () => { - Debug.Console(2, this, "PrivacyModeIsOnFeedbackFunc. IsInCall: {0} muteState: {1}", IsInCall, Configuration.Call.Microphone.Mute); + //Debug.Console(2, this, "PrivacyModeIsOnFeedbackFunc. IsInCall: {0} muteState: {1}", IsInCall, Configuration.Call.Microphone.Mute); if (IsInCall) { - Debug.Console(2, this, "reporting muteState: ", Configuration.Call.Microphone.Mute); + //Debug.Console(2, this, "reporting muteState: ", Configuration.Call.Microphone.Mute); return Configuration.Call.Microphone.Mute; } else { - Debug.Console(2, this, "muteState: true", IsInCall); - return true; + //Debug.Console(2, this, "muteState: true", IsInCall); + return false; } }; } From 939afb7aae78d3af755391f52785ef539155fa55 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 14 Sep 2022 16:40:26 -0600 Subject: [PATCH 125/202] fix(essentials): Fixes SharingSourceFeedback value to actually read FB state instead of which on screen instructions are shown --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 223d3bb4..30ec50c8 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -240,7 +240,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom protected override Func SharingSourceFeedbackFunc { - get { return () => Status.Sharing.dispState; } + get + { + return () => + { + if (Status.Sharing.isAirHostClientConnected) + return "Airplay"; + else if (Status.Sharing.isDirectPresentationConnected || Status.Sharing.isBlackMagicConnected) + return "Laptop"; + else return "None"; + + }; + } } protected override Func SharingContentIsOnFeedbackFunc @@ -743,15 +754,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Status.Sharing.PropertyChanged += (o, a) => { + SharingSourceFeedback.FireUpdate(); switch (a.PropertyName) { - case "dispState": - SharingSourceFeedback.FireUpdate(); - break; case "password": break; - case "isAirHostClientConnected": - case "isDirectPresentationConnected": case "isSharingBlackMagic": { Debug.Console(2, this, "Updating sharing status: {0}", a.PropertyName); From ee735388bbf5676581156103655a3921b57df4b2 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 15 Sep 2022 12:44:17 -0600 Subject: [PATCH 126/202] fix(essentials): reworks SIMPL bridging logic for hiding password prompt --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 25 +++++++++++-------- .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 14 ----------- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 30ec50c8..ea1b35b4 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2509,17 +2509,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom trilist.SetSigTrueAction(joinMap.ShareOnlyMeeting.JoinNumber, StartSharingOnlyMeeting); trilist.SetSigTrueAction(joinMap.StartNormalMeetingFromSharingOnlyMeeting.JoinNumber, StartNormalMeetingFromSharingOnlyMeeting); - // not sure if this would be needed here, should be handled by VideoCodecBase.cs LinkToApi methods - //DirectoryResultReturned += (device, args) => - //{ - // // add logic here if necessary when event fires - - //}; - - trilist.SetStringSigAction(joinMap.SubmitPassword.JoinNumber, SubmitPassword); - trilist.SetStringSigAction(joinMap.CancelPasswordPrompt.JoinNumber, - delegate { OnPasswordRequired(false, false, true, ""); }); + //trilist.SetSigFalseAction(joinMap.CancelPasswordPrompt.JoinNumber, () => + // OnPasswordRequired(false, false, true, "")); + + // Subscribe to call status to clear ShowPasswordPrompt when in meeting + this.CallStatusChange += (o, a) => + { + if (IsInCall) + { + trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, false); + } + + }; + PasswordRequired += (devices, args) => { if (args.LoginAttemptCancelled) @@ -3382,7 +3385,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { Debug.Console(2, this, "Password Submitted: {0}", password); Dial(_lastDialedMeetingNumber, password); - OnPasswordRequired(false, false, true, ""); + //OnPasswordRequired(false, false, true, ""); } void OnPasswordRequired(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs index b0b497de..48b2c039 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs @@ -23,20 +23,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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 [JoinName("PasswordIncorrect")] public JoinDataComplete PasswordIncorrect = new JoinDataComplete( From 47c24a237e9d82943845377354ebcbeeff735d88 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Thu, 22 Sep 2022 12:09:26 -0400 Subject: [PATCH 127/202] fix: update secretsmanager loading mechanism --- .../PepperDashEssentialsBase/Secrets/SecretsManager.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs index 95a94a24..8e0cbc55 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs @@ -148,6 +148,7 @@ namespace PepperDash.Essentials.Core { Secrets.Add(key, provider); Debug.Console(1, "Secrets provider '{0}' added to SecretsManager", key); + return; } Debug.Console(0, Debug.ErrorLogLevel.Notice, "Unable to add Provider '{0}' to Secrets. Provider with that key already exists", key ); } @@ -164,13 +165,13 @@ namespace PepperDash.Essentials.Core { Secrets.Add(key, provider); Debug.Console(1, "Secrets provider '{0}' added to SecretsManager", key); - + return; } if (overwrite) { Secrets.Add(key, provider); Debug.Console(1, Debug.ErrorLogLevel.Notice, "Provider with the key '{0}' already exists in secrets. Overwriting with new secrets provider.", key); - + return; } Debug.Console(0, Debug.ErrorLogLevel.Notice, "Unable to add Provider '{0}' to Secrets. Provider with that key already exists", key); } From bda46eb1b9c324c33254d0a476aba7a5c62f3eb0 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 22 Sep 2022 13:05:09 -0600 Subject: [PATCH 128/202] fix(essentials): adds cancel method for password prompt and adds wireless share instructions --- .../DeviceTypeInterfaces/IPasswordPrompt.cs | 7 +- .../IZoomWirelessShareInstructions.cs | 28 ++++ .../VideoCodec/ZoomRoom/ResponseObjects.cs | 13 +- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 64 +++++++- .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 144 ++++++++++++++++-- 5 files changed, 236 insertions(+), 20 deletions(-) create mode 100644 essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/IZoomWirelessShareInstructions.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs index 6ecdd775..6b3bae57 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs @@ -20,7 +20,12 @@ namespace PepperDash.Essentials.Core /// Submits the password /// /// - void SubmitPassword(string password); + void SubmitPassword(string password); + + /// + /// Cancels the password submission + /// + void CancelPasswordPrompt(); } public class PasswordPromptEventArgs : EventArgs diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/IZoomWirelessShareInstructions.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/IZoomWirelessShareInstructions.cs new file mode 100644 index 00000000..58690d3b --- /dev/null +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/IZoomWirelessShareInstructions.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using PepperDash.Essentials.Core; + +using PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom +{ + public class ShareInfoEventArgs : EventArgs + { + public zStatus.Sharing SharingStatus { get; private set; } + + public ShareInfoEventArgs(zStatus.Sharing status) + { + SharingStatus = status; + } + } + + public interface IZoomWirelessShareInstructions + { + event EventHandler ShareInfoChanged; + + zStatus.Sharing SharingState { get; } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index b5296410..66b7fb1e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -434,9 +434,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public bool supports_Web_Settings_Push { get; set; } } + public enum eDisplayState + { + None, + Laptop, + IOS, + } + public class Sharing : NotifiableObject { - private string _dispState; + private eDisplayState _dispState; private string _password; private bool _isAirHostClientConnected; private bool _isSharingBlackMagic; @@ -448,7 +455,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// Laptop client sharing key /// public string directPresentationSharingKey { get; set; } - public string dispState + public eDisplayState dispState { get { @@ -506,8 +513,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } - - /// /// IOS Airplay code /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index ea1b35b4..b753b3fc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -27,7 +27,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMuteWithUnmuteReqeust, IHasCameraAutoMode, IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting, - IHasMeetingLock, IHasMeetingRecordingWithPrompt + IHasMeetingLock, IHasMeetingRecordingWithPrompt, IZoomWirelessShareInstructions { public event EventHandler VideoUnmuteRequested; @@ -47,12 +47,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private const string JsonDelimiter = "\x0D\x0A\x7D\x0D\x0A"; private string[] Delimiters = new string[] { EchoDelimiter, JsonDelimiter, "OK\x0D\x0A", "end\x0D\x0A" }; - //"echo off\x0D\x0A\x0A\x0D\x0A" private readonly GenericQueue _receiveQueue; - //private readonly CrestronQueue _receiveQueue; - - - //private readonly Thread _receiveThread; private readonly ZoomRoomSyncState _syncState; public bool CommDebuggingIsOn; @@ -64,6 +59,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private CameraBase _selectedCamera; private string _lastDialedMeetingNumber; + private readonly ZoomRoomPropertiesConfig _props; public ZoomRoom(DeviceConfig config, IBasicCommunication comm) @@ -754,6 +750,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Status.Sharing.PropertyChanged += (o, a) => { + OnShareInfoChanged(Status.Sharing); SharingSourceFeedback.FireUpdate(); switch (a.PropertyName) { @@ -2523,8 +2520,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom }; + trilist.SetSigFalseAction(joinMap.CancelPasswordPrompt.JoinNumber, () => CancelPasswordPrompt()); + PasswordRequired += (devices, args) => { + Debug.Console(0, this, "***********************************PaswordRequired. Message: {0} Cancelled: {1} Last Incorrect: {2} Failed: {3}", args.Message, args.LoginAttemptCancelled, args.LastAttemptWasIncorrect, args.LoginAttemptFailed); + if (args.LoginAttemptCancelled) { trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, false); @@ -2559,8 +2560,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom pinCodec.NumberOfScreensFeedback.FireUpdate(); layoutSizeCodec.SelfviewPipSizeFeedback.FireUpdate(); }; + + var wirelessInfoCodec = this as IZoomWirelessShareInstructions; + if (wirelessInfoCodec != null) + { + SetSharingStateJoins(Status.Sharing, trilist, joinMap); + + wirelessInfoCodec.ShareInfoChanged += (o, a) => + { + SetSharingStateJoins(a.SharingStatus, trilist, joinMap); + }; + } } + void SetSharingStateJoins(zStatus.Sharing state, BasicTriList trilist, ZoomRoomJoinMap joinMap) + { + trilist.SetBool(joinMap.IsSharingAirplay.JoinNumber, state.isAirHostClientConnected); + trilist.SetBool(joinMap.IsSharingHdmi.JoinNumber, state.isBlackMagicConnected || state.isDirectPresentationConnected); + + trilist.SetString(joinMap.DisplayState.JoinNumber, state.dispState.ToString()); + trilist.SetString(joinMap.AirplayShareCode.JoinNumber, state.password); + trilist.SetString(joinMap.LaptopShareKey.JoinNumber, state.directPresentationSharingKey); + trilist.SetString(joinMap.WifiName.JoinNumber, state.wifiName); + trilist.SetString(joinMap.ServerName.JoinNumber, state.serverName); + } + public override void ExecuteSwitch(object selector) { var action = selector as Action; @@ -3388,6 +3412,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom //OnPasswordRequired(false, false, true, ""); } + public void CancelPasswordPrompt() + { + OnPasswordRequired(false, false, true, "Login Cancelled"); + } + void OnPasswordRequired(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) { var handler = PasswordRequired; @@ -3521,6 +3550,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } #endregion + + #region IZoomWirelessShareInstructions Members + + public event EventHandler ShareInfoChanged; + + public zStatus.Sharing SharingState + { + get + { + return Status.Sharing; + } + } + + void OnShareInfoChanged(zStatus.Sharing status) + { + var handler = ShareInfoChanged; + if (handler != null) + { + handler(this, new ShareInfoEventArgs(status)); + } + } + + #endregion } /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs index 48b2c039..d6ffb903 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs @@ -8,7 +8,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { #region Digital - // TODO [ ] Issue #868 + [JoinName("CancelPasswordPrompt")] + public JoinDataComplete CancelPasswordPrompt = new JoinDataComplete( + new JoinData + { + JoinNumber = 5, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to hide the password prompt", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("ShowPasswordPrompt")] public JoinDataComplete ShowPasswordPrompt = new JoinDataComplete( new JoinData @@ -23,7 +36,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Digital }); - // TODO [ ] Issue #868 [JoinName("PasswordIncorrect")] public JoinDataComplete PasswordIncorrect = new JoinDataComplete( new JoinData @@ -38,8 +50,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Digital }); - // TODO [ ] Issue #868 - [JoinName("PassowrdLoginFailed")] + [JoinName("PasswordLoginFailed")] public JoinDataComplete PasswordLoginFailed = new JoinDataComplete( new JoinData { @@ -53,7 +64,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Digital }); - // TODO [ ] Issue #868 [JoinName("WaitingForHost")] public JoinDataComplete WaitingForHost = new JoinDataComplete( new JoinData @@ -68,7 +78,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Digital }); - // TODO [ ] Issue #868 [JoinName("IsHost")] public JoinDataComplete IsHost = new JoinDataComplete( new JoinData @@ -83,7 +92,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Digital }); - // TODO [ ] Issue #868 [JoinName("StartMeetingNow")] public JoinDataComplete StartMeetingNow = new JoinDataComplete( new JoinData @@ -98,7 +106,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Digital }); - // TODO [ ] Issue #868 [JoinName("ShareOnlyMeeting")] public JoinDataComplete ShareOnlyMeeting = new JoinDataComplete( new JoinData @@ -113,7 +120,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Digital }); - // TODO [ ] Issue #868 [JoinName("StartNormalMeetingFromSharingOnlyMeeting")] public JoinDataComplete StartNormalMeetingFromSharingOnlyMeeting = new JoinDataComplete( new JoinData @@ -367,6 +373,40 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Digital }); + + #region Sharing Status + + [JoinName("IsSharingAirplay")] + public JoinDataComplete IsSharingAirplay = new JoinDataComplete( + new JoinData + { + JoinNumber = 250, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Indicates an Airplay source is sharing", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IsSharingHdmi")] + public JoinDataComplete IsSharingHdmi = new JoinDataComplete( + new JoinData + { + JoinNumber = 251, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Indicates an HDMI source is sharing", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + + + #endregion //[JoinName("ParticipantAudioMuteToggleStart")] //public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( // new JoinData @@ -551,6 +591,92 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.DigitalSerial }); + [JoinName("DisplayState")] + public JoinDataComplete DisplayState = new JoinDataComplete( + new JoinData + { + JoinNumber = 250, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the instructions the ZoomRoom is displaying on the monitor. ", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("AirplayShareCode")] + public JoinDataComplete AirplayShareCode = new JoinDataComplete( + new JoinData + { + JoinNumber = 251, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the current code for Airplay Sharing.", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("LaptopShareKey")] + public JoinDataComplete LaptopShareKey = new JoinDataComplete( + new JoinData + { + JoinNumber = 252, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "The alpha-only sharing key that users type into a laptop client to share with the Zoom Room.", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("LaptopSharePairingCode")] + public JoinDataComplete LaptopSharePairingCode = new JoinDataComplete( + new JoinData + { + JoinNumber = 253, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "This is the paring code that is broadcast via an ultrasonic signal from the ZRC. It is different than the user-supplied paring code. The ZRC uses a Zoom-proprietary method of advertizing the ultrasonic pairing code, so it\'s not possible to advertize it using commonly available libraries.", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("WifiName")] + public JoinDataComplete WifiName = new JoinDataComplete( + new JoinData + { + JoinNumber = 254, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the Wifi SSID used by the ZoomRoom.", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("ServerName")] + public JoinDataComplete ServerName = new JoinDataComplete( + new JoinData + { + JoinNumber = 255, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the namne of the the ZoomRoom.", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + + #endregion public ZoomRoomJoinMap(uint joinStart) From b48859d202fff6f074cca166b6f6483b4acd7471 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 22 Sep 2022 13:06:00 -0600 Subject: [PATCH 129/202] adds missing .csproj update --- .../Essentials Devices Common/Essentials Devices Common.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index fe4d5f61..c2782532 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -184,6 +184,7 @@ + From eae089cdf58e20d806ac4ac46126a7d938e9022a Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 22 Sep 2022 15:38:11 -0600 Subject: [PATCH 130/202] fix(essentials): updates to password prompt logic --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 10 +++++----- .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index b753b3fc..5aeb3be0 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2513,14 +2513,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // Subscribe to call status to clear ShowPasswordPrompt when in meeting this.CallStatusChange += (o, a) => { - if (IsInCall) + if (a.CallItem.Status == eCodecCallStatus.Connected || a.CallItem.Status == eCodecCallStatus.Disconnected) { - trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, false); + trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, false); } }; - trilist.SetSigFalseAction(joinMap.CancelPasswordPrompt.JoinNumber, () => CancelPasswordPrompt()); + trilist.SetSigFalseAction(joinMap.CancelJoinAttempt.JoinNumber, () => trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, false)); PasswordRequired += (devices, args) => { @@ -2528,7 +2528,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (args.LoginAttemptCancelled) { - trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, false); + trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, false); return; } @@ -2544,7 +2544,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } trilist.SetBool(joinMap.PasswordIncorrect.JoinNumber, args.LastAttemptWasIncorrect); - trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, true); + trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, true); }; trilist.OnlineStatusChange += (device, args) => diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs index d6ffb903..c377a664 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs @@ -8,8 +8,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { #region Digital - [JoinName("CancelPasswordPrompt")] - public JoinDataComplete CancelPasswordPrompt = new JoinDataComplete( + [JoinName("CancelJoinAttempt")] + public JoinDataComplete CancelJoinAttempt = new JoinDataComplete( new JoinData { JoinNumber = 5, @@ -22,8 +22,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Digital }); - [JoinName("ShowPasswordPrompt")] - public JoinDataComplete ShowPasswordPrompt = new JoinDataComplete( + [JoinName("MeetingPasswordRequired")] + public JoinDataComplete MeetingPasswordRequired = new JoinDataComplete( new JoinData { JoinNumber = 6, From c3d07fe4fdeda01792f19e045638c2f00d7defab Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 23 Sep 2022 08:28:32 -0600 Subject: [PATCH 131/202] fix(essentials): Adds EndAllCalls to CancelJoinAttempt action --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 5aeb3be0..d491fa59 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2520,7 +2520,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom }; - trilist.SetSigFalseAction(joinMap.CancelJoinAttempt.JoinNumber, () => trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, false)); + trilist.SetSigFalseAction(joinMap.CancelJoinAttempt.JoinNumber, () => { + trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, false); + EndAllCalls(); + }); PasswordRequired += (devices, args) => { From 05ec0ebac35a6c23a6f92ebfeefb0bc19b12edee Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 23 Sep 2022 12:27:55 -0600 Subject: [PATCH 132/202] fix(essentials): Adds ability to dial up to 10 calls from SIMPL bridge --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 36 ++------------- .../VideoCodec/VideoCodecBase.cs | 46 +++++++------------ 2 files changed, 20 insertions(+), 62 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index d1b383b0..7fc0626a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -776,44 +776,16 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("DialMeeting1")] - public JoinDataComplete DialMeeting1 = new JoinDataComplete( + [JoinName("DialMeetingStart")] + public JoinDataComplete DialMeetingStart = new JoinDataComplete( new JoinData { JoinNumber = 161, - JoinSpan = 1 + JoinSpan = 10 }, new JoinMetadata { - Description = "Join first meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting2")] - public JoinDataComplete DialMeeting2 = new JoinDataComplete( - new JoinData - { - JoinNumber = 162, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Join second meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting3")] - public JoinDataComplete DialMeeting3 = new JoinDataComplete( - new JoinData - { - JoinNumber = 163, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Join third meeting", + Description = "Join meeting", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 1270b690..0626044d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -804,35 +804,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec codec.CodecSchedule.MeetingWarningMinutes = i; }); - trilist.SetSigFalseAction(joinMap.DialMeeting1.JoinNumber, () => - { - var mtg = 1; - var index = mtg - 1; - Debug.Console(1, this, "Meeting {0} Selected (EISC dig-o{1}) > _currentMeetings[{2}].Id: {3}, Title: {4}", - mtg, joinMap.DialMeeting1.JoinNumber, index, _currentMeetings[index].Id, _currentMeetings[index].Title); - if (_currentMeetings[index] != null) - Dial(_currentMeetings[index]); - }); - - trilist.SetSigFalseAction(joinMap.DialMeeting2.JoinNumber, () => - { - var mtg = 2; - var index = mtg - 1; - Debug.Console(1, this, "Meeting {0} Selected (EISC dig-o{1}) > _currentMeetings[{2}].Id: {3}, Title: {4}", - mtg, joinMap.DialMeeting2.JoinNumber, index, _currentMeetings[index].Id, _currentMeetings[index].Title); - if (_currentMeetings[index] != null) - Dial(_currentMeetings[index]); - }); - - trilist.SetSigFalseAction(joinMap.DialMeeting3.JoinNumber, () => - { - var mtg = 3; - var index = mtg - 1; - Debug.Console(1, this, "Meeting {0} Selected (EISC dig-o{1}) > _currentMeetings[{2}].Id: {3}, Title: {4}", - mtg, joinMap.DialMeeting3.JoinNumber, index, _currentMeetings[index].Id, _currentMeetings[index].Title); - if (_currentMeetings[index] != null) - Dial(_currentMeetings[index]); - }); + + for (uint i = 0; i < joinMap.DialMeetingStart.JoinSpan; i++) + { + Debug.Console(1, this, "Setting action to Dial Meeting {0} to digital join {1}", i + 1, joinMap.DialMeetingStart.JoinNumber + i); + var joinNumber = joinMap.DialMeetingStart.JoinNumber + i; + var mtg = i + 1; + var index = (int)i; + + trilist.SetSigFalseAction(joinNumber, () => + { + Debug.Console(1, this, "Meeting {0} Selected (EISC dig-o{1}) > _currentMeetings[{2}].Id: {3}, Title: {4}", + mtg, joinMap.DialMeetingStart.JoinNumber + i, index, _currentMeetings[index].Id, _currentMeetings[index].Title); + if (_currentMeetings[index] != null) + Dial(_currentMeetings[index]); + }); + } codec.CodecSchedule.MeetingsListHasChanged += (sender, args) => UpdateMeetingsList(codec, trilist, joinMap); codec.CodecSchedule.MeetingEventChange += (sender, args) => @@ -843,7 +830,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } }; - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set trilist.SetUShortSigAction(joinMap.MeetingsToDisplay.JoinNumber, m => MeetingsToDisplay = m); MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]); From a524b1607d88391d5a648beb08e3f2bd8356f8c7 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 28 Sep 2022 12:28:37 -0600 Subject: [PATCH 133/202] fix(essentials): Updates to deal with layouts and default layout for ZoomRoom --- .../DeviceTypeInterfaces/IPasswordPrompt.cs | 109 +++++++++--------- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 18 +++ .../VideoCodec/ZoomRoom/ZoomRoom.cs | 42 ++++--- .../ZoomRoom/ZoomRoomPropertiesConfig.cs | 7 +- 4 files changed, 98 insertions(+), 78 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs index 6b3bae57..da61bbc0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs @@ -1,61 +1,56 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -namespace PepperDash.Essentials.Core -{ - /// - /// Describes the functionality required to prompt a user to enter a password - /// - public interface IPasswordPrompt - { - /// - /// Notifies when a password is required or is entered incorrectly - /// - event EventHandler PasswordRequired; - - /// - /// Submits the password - /// - /// - void SubmitPassword(string password); +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Essentials.Core +{ + /// + /// Describes the functionality required to prompt a user to enter a password + /// + public interface IPasswordPrompt + { + /// + /// Notifies when a password is required or is entered incorrectly + /// + event EventHandler PasswordRequired; /// - /// Cancels the password submission + /// Submits the password /// - void CancelPasswordPrompt(); - } - - public class PasswordPromptEventArgs : EventArgs - { - /// - /// Indicates if the last submitted password was incorrect - /// - public bool LastAttemptWasIncorrect { get; private set; } - - /// - /// Indicates that the login attempt has failed - /// - public bool LoginAttemptFailed { get; private set; } - - /// - /// Indicates that the process was cancelled and the prompt should be dismissed - /// - public bool LoginAttemptCancelled { get; private set; } - - /// - /// A message to be displayed to the user - /// - public string Message { get; private set; } - - public PasswordPromptEventArgs(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) - { - LastAttemptWasIncorrect = lastAttemptIncorrect; - LoginAttemptFailed = loginFailed; - LoginAttemptCancelled = loginCancelled; - Message = message; - } - } + /// + void SubmitPassword(string password); + } + + public class PasswordPromptEventArgs : EventArgs + { + /// + /// Indicates if the last submitted password was incorrect + /// + public bool LastAttemptWasIncorrect { get; private set; } + + /// + /// Indicates that the login attempt has failed + /// + public bool LoginAttemptFailed { get; private set; } + + /// + /// Indicates that the process was cancelled and the prompt should be dismissed + /// + public bool LoginAttemptCancelled { get; private set; } + + /// + /// A message to be displayed to the user + /// + public string Message { get; private set; } + + public PasswordPromptEventArgs(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) + { + LastAttemptWasIncorrect = lastAttemptIncorrect; + LoginAttemptFailed = loginFailed; + LoginAttemptCancelled = loginCancelled; + Message = message; + } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index 66b7fb1e..8ace1e71 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -627,6 +627,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // backer variables private bool _can_Switch_Speaker_View; private bool _can_Switch_Wall_View; + private bool _can_Switch_Strip_View; private bool _can_Switch_Share_On_All_Screens; private bool _can_Switch_Floating_Share_Content; private bool _is_In_First_Page; @@ -714,6 +715,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } + [JsonProperty("can_Switch_Strip_View")] + public bool can_Switch_Strip_View + { + get + { + return _can_Switch_Strip_View; + } + set + { + if (value != _can_Switch_Strip_View) + { + _can_Switch_Strip_View = value; + NotifyPropertyChanged("can_Switch_Strip_View"); + } + } + } + [JsonProperty("is_In_First_Page")] public bool is_In_First_Page { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index d491fa59..61737c90 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -810,8 +810,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Debug.Console(1, this, "Status.Layout.PropertyChanged a.PropertyName: {0}", a.PropertyName); switch (a.PropertyName.ToLower()) { - case "can_switch_speaker_view": + case "can_Switch_speaker_view": case "can_switch_wall_view": + case "can_switch_strip_view": + case "video_type": case "can_switch_share_on_all_screens": { ComputeAvailableLayouts(); @@ -827,7 +829,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom LayoutViewIsOnLastPageFeedback.FireUpdate(); break; } - case "can_Switch_Floating_Share_Content": + case "can_switch_floating_share_content": { CanSwapContentWithThumbnailFeedback.FireUpdate(); break; @@ -1559,7 +1561,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Sharing); - SetLayout(); + SetDefaultLayout(); break; } @@ -1935,7 +1937,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } - private void SetLayout() + private void SetDefaultLayout() { if (!_props.AutoDefaultLayouts) return; @@ -1948,8 +1950,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } else { - SendText(String.Format("zconfiguration call layout style: {0}", - _props.DefaultCallLayout)); + if (_props.DefaultCallLayout == (_props.DefaultCallLayout & AvailableLayouts)) + { + SendText(String.Format("zconfiguration call layout style: {0}", + _props.DefaultCallLayout)); + } + else + Debug.Console(0, this, "Unable to set default Layout. {0} not currently an available layout based on meeting state", _props.DefaultCallLayout); } } @@ -2149,8 +2156,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue ); + + SetDefaultLayout(); } - // TODO [ ] Issue #868 + else if (item.Status == eCodecCallStatus.Disconnected) { MeetingInfo = new MeetingInfo( @@ -2171,11 +2180,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Debug.Console(1, this, "[OnCallStatusChange] Current Call Status: {0}", Status.Call != null ? Status.Call.Status.ToString() : "no call"); - - if (_props.AutoDefaultLayouts) - { - SetLayout(); - } } private string GetSharingStatus() @@ -3264,7 +3268,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // There is no property that directly reports if strip mode is valid, but API stipulates // that strip mode is available if the number of screens is 1 - if (Status.NumberOfScreens.NumOfScreens == 1) + if (Status.NumberOfScreens.NumOfScreens == 1 || Status.Layout.can_Switch_Strip_View || Status.Layout.video_type.ToLower() == "strip") { availableLayouts |= zConfiguration.eLayoutStyle.Strip; } @@ -3279,10 +3283,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var handler = LayoutInfoChanged; if (handler != null) { + + var currentLayout = zConfiguration.eLayoutStyle.None; + + currentLayout = (zConfiguration.eLayoutStyle)Enum.Parse(typeof(zConfiguration.eLayoutStyle), string.IsNullOrEmpty(LocalLayoutFeedback.StringValue) ? "None" : LocalLayoutFeedback.StringValue, true); + handler(this, new LayoutInfoChangedEventArgs() { AvailableLayouts = AvailableLayouts, - CurrentSelectedLayout = (zConfiguration.eLayoutStyle)Enum.Parse(typeof(zConfiguration.eLayoutStyle),string.IsNullOrEmpty(LocalLayoutFeedback.StringValue) ? "None" : LocalLayoutFeedback.StringValue , true), + CurrentSelectedLayout = currentLayout, LayoutViewIsOnFirstPage = LayoutViewIsOnFirstPageFeedback.BoolValue, LayoutViewIsOnLastPage = LayoutViewIsOnLastPageFeedback.BoolValue, CanSwapContentWithThumbnail = CanSwapContentWithThumbnailFeedback.BoolValue, @@ -3415,11 +3424,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom //OnPasswordRequired(false, false, true, ""); } - public void CancelPasswordPrompt() - { - OnPasswordRequired(false, false, true, "Login Cancelled"); - } - void OnPasswordRequired(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) { var handler = PasswordRequired; diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs index 3f752f43..771cfe11 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomPropertiesConfig.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using Crestron.SimplSharp; using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using PepperDash.Core; using PepperDash.Essentials.Core; @@ -29,11 +30,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /* This layout will be selected when Sharing starts (either from Far end or locally)*/ [JsonProperty("defaultSharingLayout")] - public string DefaultSharingLayout { get; set; } + [JsonConverter(typeof(StringEnumConverter))] + public zConfiguration.eLayoutStyle DefaultSharingLayout { get; set; } //This layout will be selected when a call is connected and no content is being shared [JsonProperty("defaultCallLayout")] - public string DefaultCallLayout { get; set; } + [JsonConverter(typeof(StringEnumConverter))] + public zConfiguration.eLayoutStyle DefaultCallLayout { get; set; } [JsonProperty("minutesBeforeMeetingStart")] public int MinutesBeforeMeetingStart { get; set; } From 4deb9a08287163f9a0b749683639d91c4e1716bc Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 28 Sep 2022 14:55:14 -0600 Subject: [PATCH 134/202] fix(essentials): Updates to deal with sharing status and adds a property to notify if meeting can be recorded --- .../VideoCodec/Interfaces/IHasMeetingInfo.cs | 9 ++- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 47 ++++++++++++++- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 60 ++++++++++++------- .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 14 +++++ 4 files changed, 102 insertions(+), 28 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs index cfe70e1b..4d27535a 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasMeetingInfo.cs @@ -43,10 +43,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces [JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)] public Boolean IsLocked { get; private set; } [JsonProperty("isRecording", NullValueHandling = NullValueHandling.Ignore)] - public Boolean IsRecording { get; private set; } + public Boolean IsRecording { get; private set; } + [JsonProperty("canRecord", NullValueHandling = NullValueHandling.Ignore)] + public Boolean CanRecord { get; private set; } - public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked, bool isRecording) + public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked, bool isRecording, bool canRecord) { Id = id; Name = name; @@ -57,7 +59,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces IsSharingMeeting = isSharingMeeting; WaitingForHost = waitingForHost; IsLocked = isLocked; - IsRecording = isRecording; + IsRecording = isRecording; + CanRecord = CanRecord; } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index 8ace1e71..1518c9d5 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -793,11 +793,43 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public class CallRecordInfo : NotifiableObject { private bool _meetingIsBeingRecorded; + private bool _canRecord; + private bool _emailRequired; - public bool canRecord { get; set; } - public bool emailRequired { get; set; } public bool amIRecording { get; set; } + public bool canRecord + { + get + { + return _canRecord; + } + set + { + if (value != _canRecord) + { + _canRecord = value; + NotifyPropertyChanged("canRecord"); + } + } + } + + public bool emailRequired + { + get + { + return _emailRequired; + } + set + { + if (value != _emailRequired) + { + _emailRequired = value; + NotifyPropertyChanged("emailRequired"); + } + } + } + public bool meetingIsBeingRecorded { get @@ -816,6 +848,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } + /// + /// Indicates if recording is allowed (when meeting capable and and email is not required to be entered by the user) + /// + public bool AllowRecord + { + get + { + return canRecord && !emailRequired; + } + } + public CallRecordInfo() { Debug.Console(2, Debug.ErrorLogLevel.Notice, "********************************************* CallRecordInfo() ******************************************"); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 61737c90..a3b2cc8b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -529,6 +529,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// private void SetUpCallFeedbackActions() { + Status.Sharing.PropertyChanged -= HandleSharingStateUpdate; + Status.Sharing.PropertyChanged += HandleSharingStateUpdate; + Status.Call.Sharing.PropertyChanged -= HandleSharingStateUpdate; Status.Call.Sharing.PropertyChanged += HandleSharingStateUpdate; @@ -541,7 +544,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void HandleCallRecordInfoStateUpdate(object sender, PropertyChangedEventArgs a) { - if (a.PropertyName == "meetingIsBeingRecorded") + if (a.PropertyName == "meetingIsBeingRecorded" || a.PropertyName == "emailRequired" || a.PropertyName == "canRecord") { MeetingIsRecordingFeedback.FireUpdate(); @@ -554,7 +557,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, - MeetingIsRecordingFeedback.BoolValue); + MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); MeetingInfo = meetingInfo; } } @@ -580,10 +583,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void HandleSharingStateUpdate(object sender, PropertyChangedEventArgs a) { - if (a.PropertyName != "State") - { - return; - } + //if (a.PropertyName != "State") + //{ + // return; + //} SharingContentIsOnFeedback.FireUpdate(); ReceivingContent.FireUpdate(); @@ -593,21 +596,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // Update the share status of the meeting info if (MeetingInfo == null) { - var sharingStatus = GetSharingStatus(); - - MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue); + MeetingInfo = new MeetingInfo("", "", "", "", GetSharingStatus(), GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); return; } 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, MeetingIsRecordingFeedback.BoolValue); + MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); MeetingInfo = meetingInfo; } catch (Exception e) { Debug.Console(1, this, "Error processing state property update. {0}", e.Message); Debug.Console(2, this, e.StackTrace); - MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue); + MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, false); } } @@ -714,7 +715,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, - MeetingIsRecordingFeedback.BoolValue + MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord ); } }; @@ -776,7 +777,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, - MeetingIsRecordingFeedback.BoolValue); + MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); MeetingInfo = meetingInfo; break; } @@ -1470,13 +1471,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, - MeetingInfo.Password, - MeetingInfo.ShareStatus, + MeetingInfo.Password, + GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, - MeetingIsRecordingFeedback.BoolValue); + MeetingIsRecordingFeedback.BoolValue, + Status.Call.CallRecordInfo.AllowRecord + ); MeetingInfo = meetingInfo; PrintCurrentCallParticipants(); @@ -1691,14 +1694,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (MeetingInfo == null) { MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", - GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue); + GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); UpdateCallStatus(); break; } MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", - GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue); + GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); UpdateCallStatus(); @@ -1708,12 +1711,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (MeetingInfo == null) { MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", - GetSharingStatus(), false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue); + GetSharingStatus(), false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); break; } MeetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, - GetSharingStatus(), GetIsHostMyself(), false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue); + GetSharingStatus(), GetIsHostMyself(), false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); break; } @@ -1803,7 +1806,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (result.Success) { - MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue); + MeetingInfo = new MeetingInfo("", "", "", "", GetSharingStatus(), true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord); break; } @@ -2154,7 +2157,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom !String.Equals(Status.Call.Info.meeting_type,"NORMAL"), false, MeetingIsLockedFeedback.BoolValue, - MeetingIsRecordingFeedback.BoolValue + MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord ); SetDefaultLayout(); @@ -2172,7 +2175,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom false, false, false, - false + false, Status.Call.CallRecordInfo.AllowRecord ); } @@ -2392,6 +2395,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// public void LinkZoomRoomToApi(BasicTriList trilist, ZoomRoomJoinMap joinMap) { + var meetingInfoCodec = this as IHasMeetingInfo; + if (meetingInfoCodec != null) + { + trilist.SetBool(joinMap.MeetingCanRecord.JoinNumber, meetingInfoCodec.MeetingInfo.CanRecord); + + meetingInfoCodec.MeetingInfoChanged += (o, a) => + { + trilist.SetBool(joinMap.MeetingCanRecord.JoinNumber, a.Info.CanRecord); + }; + } + var recordingCodec = this as IHasMeetingRecordingWithPrompt; if (recordingCodec != null) { diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs index c377a664..7affd835 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs @@ -373,6 +373,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Digital }); + [JoinName("MeetingCanRecord")] + public JoinDataComplete MeetingCanRecord = new JoinDataComplete( + new JoinData + { + JoinNumber = 246, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "When high, indicated that the current meeting can be recorded", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + #region Sharing Status From 3670bde7cf944a45ca49dac91a5ebe826e95263e Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 29 Sep 2022 10:53:55 -0600 Subject: [PATCH 135/202] fix(essentials): Adds extra private field to trigger OnShareInfoChanged --- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 14 +++++++++++++- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 12 ++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index 1518c9d5..0075b657 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -448,6 +448,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private bool _isAirHostClientConnected; private bool _isSharingBlackMagic; private bool _isDirectPresentationConnected; + private bool _isBlackMagicConnected; public string directPresentationPairingCode { get; set; } @@ -484,7 +485,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } - public bool isBlackMagicConnected { get; set; } + public bool isBlackMagicConnected + { + get { return _isBlackMagicConnected; } + set + { + if (value != _isBlackMagicConnected) + { + _isBlackMagicConnected = value; + NotifyPropertyChanged("isBlackMagicConnected"); + } + } + } public bool isBlackMagicDataAvailable { get; set; } public bool isDirectPresentationConnected diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index a3b2cc8b..438e4400 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -3586,6 +3586,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom void OnShareInfoChanged(zStatus.Sharing status) { + Debug.Console(2, this, +@"ShareInfoChanged: +isSharingHDMI: {0} +isSharingAirplay: {1} +AirplayPassword: {2} +OSD Display State: {3} +", +status.isSharingBlackMagic, +status.isAirHostClientConnected, +status.password, +status.dispState); + var handler = ShareInfoChanged; if (handler != null) { From 4938071f70c1177a4280ef4f11daa760d449eecc Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 29 Sep 2022 11:22:13 -0600 Subject: [PATCH 136/202] fix(essentials): Updates the func to return whether sharing content --- .../Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 438e4400..36b13c19 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -252,7 +252,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom protected override Func SharingContentIsOnFeedbackFunc { - get { return () => Status.Call.Sharing.IsSharing; } + get { return () => Status.Sharing.isAirHostClientConnected || Status.Sharing.isDirectPresentationConnected || Status.Sharing.isSharingBlackMagic; } } protected Func FarEndIsSharingContentFeedbackFunc From 55031d16aff5de0b5f86fbf5c1deab9e17560e91 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 29 Sep 2022 12:33:42 -0600 Subject: [PATCH 137/202] docs(essentials): Add join name to printjoinmap and update description on StartMeetingNow join --- .../PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs | 3 ++- .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs index aa8e2e6d..04abc7f8 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs @@ -283,9 +283,10 @@ namespace PepperDash.Essentials.Core foreach (var join in joins) { Debug.Console(0, - @"Join Number: {0} | JoinSpan: '{1}' | Description: '{2}' | Type: '{3}' | Capabilities: '{4}'", + @"Join Number: {0} | JoinSpan: '{1}' | JoinName: {2} | Description: '{3}' | Type: '{4}' | Capabilities: '{5}'", join.Value.JoinNumber, join.Value.JoinSpan, + join.Key, String.IsNullOrEmpty(join.Value.AttributeName) ? join.Value.Metadata.Label : join.Value.AttributeName, join.Value.Metadata.JoinType.ToString(), join.Value.Metadata.JoinCapabilities.ToString()); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs index 7affd835..878f88d5 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs @@ -101,7 +101,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom }, new JoinMetadata { - Description = "FB Indicates the password prompt is active", + Description = "Pulse to start an ad-hoc meeting with the default duration", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); From dbd77f5f9f56334ebfea5c8a4ba9980760bef834 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 29 Sep 2022 12:35:05 -0600 Subject: [PATCH 138/202] fix(essentials): Switch to SetSigTrueAction for a few joins --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 36b13c19..b6763609 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2520,9 +2520,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom //trilist.SetString(joinMap.CurrentSource.JoinNumber, args.Info.ShareStatus); }; - trilist.SetSigTrueAction(joinMap.StartMeetingNow.JoinNumber, () => StartMeeting(0)); - trilist.SetSigTrueAction(joinMap.ShareOnlyMeeting.JoinNumber, StartSharingOnlyMeeting); - trilist.SetSigTrueAction(joinMap.StartNormalMeetingFromSharingOnlyMeeting.JoinNumber, StartNormalMeetingFromSharingOnlyMeeting); + trilist.SetSigFalseAction(joinMap.StartMeetingNow.JoinNumber, () => StartMeeting(0)); + trilist.SetSigFalseAction(joinMap.ShareOnlyMeeting.JoinNumber, StartSharingOnlyMeeting); + trilist.SetSigFalseAction(joinMap.StartNormalMeetingFromSharingOnlyMeeting.JoinNumber, StartNormalMeetingFromSharingOnlyMeeting); trilist.SetStringSigAction(joinMap.SubmitPassword.JoinNumber, SubmitPassword); //trilist.SetSigFalseAction(joinMap.CancelPasswordPrompt.JoinNumber, () => From f82b7f8f12b8dffec526d3203d3dac5694d33a53 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 29 Sep 2022 13:33:15 -0600 Subject: [PATCH 139/202] refactor(essentials): cleans up some args names for clarity --- .../Interfaces/IHasPresentationOnlyMeeting.cs | 6 +++--- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 15 +++++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs index 06730d2a..a76a6da2 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs @@ -3,9 +3,9 @@ public interface IHasPresentationOnlyMeeting { void StartSharingOnlyMeeting(); - void StartSharingOnlyMeeting(eSharingMeetingMode mode); - void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration); - void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration, string password); + void StartSharingOnlyMeeting(eSharingMeetingMode displayMode); + void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, ushort duration); + void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, ushort duration, string password); void StartNormalMeetingFromSharingOnlyMeeting(); } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index b6763609..7942b61e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2250,6 +2250,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } + /// + /// Starts sharing HDMI source + /// public override void StartSharing() { SendText("zCommand Call Sharing HDMI Start"); @@ -3482,19 +3485,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom StartSharingOnlyMeeting(eSharingMeetingMode.None, 30, String.Empty); } - public void StartSharingOnlyMeeting(eSharingMeetingMode mode) + public void StartSharingOnlyMeeting(eSharingMeetingMode displayMode) { - StartSharingOnlyMeeting(mode, 30, String.Empty); + StartSharingOnlyMeeting(displayMode, DefaultMeetingDurationMin, String.Empty); } - public void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration) + public void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, ushort duration) { - StartSharingOnlyMeeting(mode, duration, String.Empty); + StartSharingOnlyMeeting(displayMode, duration, String.Empty); } - public void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration, string password) + public void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration, string password) { - SendText(String.Format("zCommand Dial Sharing Duration: {0} DisplayState: {1} Password: {2}", duration, mode, password)); + SendText(String.Format("zCommand Dial Sharing Duration: {0} DisplayState: {1} Password: {2}", duration, displayMode, password)); } public void StartNormalMeetingFromSharingOnlyMeeting() From ca1cbb6e05201d7b881dc39b69c60a8eea0ce415 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 29 Sep 2022 14:11:41 -0600 Subject: [PATCH 140/202] fix(essentials): Resolves null ref in LinkZoomRoomToApi --- .../Interfaces/IHasPresentationOnlyMeeting.cs | 4 ++-- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 14 +++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs index a76a6da2..a620af1e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs @@ -4,8 +4,8 @@ { void StartSharingOnlyMeeting(); void StartSharingOnlyMeeting(eSharingMeetingMode displayMode); - void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, ushort duration); - void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, ushort duration, string password); + void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration); + void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration, string password); void StartNormalMeetingFromSharingOnlyMeeting(); } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 7942b61e..820d3ab1 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2401,7 +2401,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var meetingInfoCodec = this as IHasMeetingInfo; if (meetingInfoCodec != null) { - trilist.SetBool(joinMap.MeetingCanRecord.JoinNumber, meetingInfoCodec.MeetingInfo.CanRecord); + if (meetingInfoCodec.MeetingInfo != null) + { + trilist.SetBool(joinMap.MeetingCanRecord.JoinNumber, meetingInfoCodec.MeetingInfo.CanRecord); + } meetingInfoCodec.MeetingInfoChanged += (o, a) => { @@ -2528,8 +2531,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom trilist.SetSigFalseAction(joinMap.StartNormalMeetingFromSharingOnlyMeeting.JoinNumber, StartNormalMeetingFromSharingOnlyMeeting); trilist.SetStringSigAction(joinMap.SubmitPassword.JoinNumber, SubmitPassword); - //trilist.SetSigFalseAction(joinMap.CancelPasswordPrompt.JoinNumber, () => - // OnPasswordRequired(false, false, true, "")); // Subscribe to call status to clear ShowPasswordPrompt when in meeting this.CallStatusChange += (o, a) => @@ -2588,7 +2589,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var wirelessInfoCodec = this as IZoomWirelessShareInstructions; if (wirelessInfoCodec != null) { - SetSharingStateJoins(Status.Sharing, trilist, joinMap); + if (Status != null && Status.Sharing != null) + { + SetSharingStateJoins(Status.Sharing, trilist, joinMap); + } wirelessInfoCodec.ShareInfoChanged += (o, a) => { @@ -3490,7 +3494,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom StartSharingOnlyMeeting(displayMode, DefaultMeetingDurationMin, String.Empty); } - public void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, ushort duration) + public void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration) { StartSharingOnlyMeeting(displayMode, duration, String.Empty); } From 4fb2d6d75576c376650f3a9a9873fcb070d3d5ae Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 5 Oct 2022 16:13:53 -0500 Subject: [PATCH 141/202] fix: updated XSig methods in VideoCodecBase --- .../Essentials Devices Common/VideoCodec/VideoCodecBase.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 9fae1a99..b6fe5dcc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1407,9 +1407,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec arrayIndex += offset; stringIndex += maxStrings; - digitalIndex++; + digitalIndex += maxDigitals; } - while (digitalIndex < maxCalls) + while (digitalIndex < maxCalls * offset) { //digitals tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); @@ -1426,7 +1426,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec arrayIndex += offset; stringIndex += maxStrings; - digitalIndex++; + digitalIndex += maxDigitals; } return GetXSigString(tokenArray); From 62275890cb8648c33dd431be9598364405b025be Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Thu, 6 Oct 2022 00:38:02 -0500 Subject: [PATCH 142/202] style: changed tracking variable in UpdateCallStatusXsig --- .../Essentials Devices Common/VideoCodec/VideoCodecBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index b6fe5dcc..bea5862c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1409,7 +1409,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec stringIndex += maxStrings; digitalIndex += maxDigitals; } - while (digitalIndex < maxCalls * offset) + while (arrayIndex < maxCalls * offset) { //digitals tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); From 040c57b5e10abbe2b8b9ec1723d736bcba90fbdb Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 6 Oct 2022 10:05:44 -0600 Subject: [PATCH 143/202] fix(essentials): Updates to shade interfaces to clarify functionality --- .../EssentialsShadeDriver.cs | 8 ++--- .../Shades/Shade Interfaces.cs | 35 +++++++++++++------ .../Shades/ShadeBase.cs | 4 +-- .../Environment/Somfy/RelayControlledShade.cs | 4 +-- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/PepperDashEssentials/UIDrivers/Environment Drivers/EssentialsShadeDriver.cs b/PepperDashEssentials/UIDrivers/Environment Drivers/EssentialsShadeDriver.cs index b62e047c..fb40252c 100644 --- a/PepperDashEssentials/UIDrivers/Environment Drivers/EssentialsShadeDriver.cs +++ b/PepperDashEssentials/UIDrivers/Environment Drivers/EssentialsShadeDriver.cs @@ -97,10 +97,10 @@ namespace PepperDash.Essentials { TriList.SetSigFalseAction(ButtonPressJoinBase + 1, ShadeDevice.Open); - TriList.SetSigFalseAction(ButtonPressJoinBase + 2, (ShadeDevice as IShadesOpenCloseStop).StopOrPreset); - - if(ShadeDevice is RelayControlledShade) - TriList.SetString(StringJoinBase + 2, (ShadeDevice as RelayControlledShade).StopOrPresetButtonLabel); + TriList.SetSigFalseAction(ButtonPressJoinBase + 2, (ShadeDevice as IShadesOpenCloseStop).Stop); + + if (ShadeDevice is IShadesOpenCloseStop) + TriList.SetString(StringJoinBase + 2, "Stop"); TriList.SetSigFalseAction(ButtonPressJoinBase + 3, ShadeDevice.Close); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Shades/Shade Interfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Shades/Shade Interfaces.cs index 35492162..949009f6 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Shades/Shade Interfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Shades/Shade Interfaces.cs @@ -19,6 +19,7 @@ namespace PepperDash.Essentials.Core.Shades /// /// Requirements for a device that implements basic Open/Close shade control /// + [Obsolete("Please use IShadesOpenCloseStop instead")] public interface IShadesOpenClose { void Open(); @@ -28,15 +29,26 @@ namespace PepperDash.Essentials.Core.Shades /// /// Requirements for a device that implements basic Open/Close/Stop shade control (Uses 3 relays) /// - public interface IShadesOpenCloseStop : IShadesOpenClose - { - void StopOrPreset(); - string StopOrPresetButtonLabel { get; } + public interface IShadesOpenCloseStop + { + void Open(); + void Close(); + void Stop(); + } + + public interface IShadesOpenClosePreset : IShadesOpenCloseStop + { + void RecallPreset(uint presetNumber); + void SavePreset(uint presetNumber); + string StopOrPresetButtonLabel { get; } + + event EventHandler PresetSaved; } /// /// Requirements for a shade that implements press/hold raise/lower functions - /// + /// + [Obsolete("Please use IShadesOpenCloseStop instead")] public interface IShadesRaiseLower { void Raise(bool state); @@ -55,7 +67,7 @@ namespace PepperDash.Essentials.Core.Shades /// /// Requirements for a shade/scene that is open or closed /// - public interface IShadesOpenClosedFeedback: IShadesOpenClose + public interface IShadesOpenClosedFeedback: IShadesOpenCloseStop { BoolFeedback ShadeIsOpenFeedback { get; } BoolFeedback ShadeIsClosedFeedback { get; } @@ -63,15 +75,16 @@ namespace PepperDash.Essentials.Core.Shades /// /// - /// - public interface IShadesStop + /// + [Obsolete("Please use IShadesOpenCloseStop instead")] + public interface IShadesStop { void Stop(); } /// - /// - /// + /// Used to implement raise/stop/lower/stop from single button + /// public interface IShadesStopOrMove { void OpenOrStop(); @@ -82,7 +95,7 @@ namespace PepperDash.Essentials.Core.Shades /// /// Basic feedback for shades/scene stopped /// - public interface IShadesStopFeedback + public interface IShadesStopFeedback : IShadesOpenCloseStop { BoolFeedback IsStoppedFeedback { get; } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Shades/ShadeBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Shades/ShadeBase.cs index d30b716a..2b92480e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Shades/ShadeBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Shades/ShadeBase.cs @@ -12,7 +12,7 @@ namespace PepperDash.Essentials.Core.Shades /// /// Base class for a shade device /// - public abstract class ShadeBase : EssentialsDevice, IShadesOpenClose + public abstract class ShadeBase : EssentialsDevice, IShadesOpenCloseStop { public ShadeBase(string key, string name) : base(key, name) @@ -23,7 +23,7 @@ namespace PepperDash.Essentials.Core.Shades #region iShadesOpenClose Members public abstract void Open(); - public abstract void StopOrPreset(); + public abstract void Stop(); public abstract void Close(); #endregion diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Environment/Somfy/RelayControlledShade.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Environment/Somfy/RelayControlledShade.cs index a78e5045..852d554f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Environment/Somfy/RelayControlledShade.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Environment/Somfy/RelayControlledShade.cs @@ -56,9 +56,9 @@ namespace PepperDash.Essentials.Devices.Common.Environment.Somfy PulseOutput(OpenRelay, RelayPulseTime); } - public override void StopOrPreset() + public override void Stop() { - Debug.Console(1, this, "Stopping or recalling preset on Shade: '{0}'", this.Name); + Debug.Console(1, this, "Stopping Shade: '{0}'", this.Name); PulseOutput(StopOrPresetRelay, RelayPulseTime); } From 330bb2d0023420c0d2ac2fd4f91d317b95561cea Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 13 Oct 2022 11:13:17 -0600 Subject: [PATCH 144/202] fix(essentials): #1017 -Send command to select camera by ID --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 820d3ab1..bcc3886e 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -366,26 +366,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void SelectCamera(string key) { - if (Cameras == null) - { - return; - } + if (CameraIsMutedFeedback.BoolValue) + { + CameraMuteOff(); + } - var camera = Cameras.FirstOrDefault(c => c.Key.IndexOf(key, StringComparison.OrdinalIgnoreCase) > -1); - if (camera != null) - { - Debug.Console(1, this, "Selected Camera with key: '{0}'", camera.Key); - SelectedCamera = camera; - - if (CameraIsMutedFeedback.BoolValue) - { - CameraMuteOff(); - } - } - else - { - Debug.Console(1, this, "Unable to select camera with key: '{0}'", key); - } + SendText(string.Format("zConfiguration Video Camera selectedId: {0}", key)); } public CameraBase FarEndCamera { get; private set; } @@ -648,8 +634,27 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { if (a.PropertyName == "SelectedId") { - SelectCamera(Configuration.Video.Camera.SelectedId); - // this will in turn fire the affected feedbacks + if (Cameras == null) + { + return; + } + + var camera = Cameras.FirstOrDefault(c => c.Key.IndexOf(Configuration.Video.Camera.SelectedId, StringComparison.OrdinalIgnoreCase) > -1); + if (camera != null) + { + Debug.Console(1, this, "Camera selected with key: '{0}'", camera.Key); + + SelectedCamera = camera; + + if (CameraIsMutedFeedback.BoolValue) + { + CameraMuteOff(); + } + } + else + { + Debug.Console(1, this, "No camera found with key: '{0}'", Configuration.Video.Camera.SelectedId); + } } }; From f3fc0f2b2626d604b970aefc32a05aa4fcf1c3ff Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Tue, 18 Oct 2022 10:51:24 -0500 Subject: [PATCH 145/202] fix: update xSig Method for active call status --- .../VideoCodec/VideoCodecBase.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index bea5862c..44d3f423 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1393,11 +1393,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, call.IsOnHold); //serials - tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); - tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, call.Number ?? String.Empty); - tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString()); - tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 4, call.Type.ToString()); - tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 5, call.Status.ToString()); + tokenArray[arrayIndex] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); + tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 2, call.Number ?? String.Empty); + tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString()); + tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 4, call.Type.ToString()); + tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 5, call.Status.ToString()); if(call.Duration != null) { // May need to verify correct string format here @@ -1417,12 +1417,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //serials - tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty); - tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty); - tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty); - tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 4, String.Empty); - tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 5, String.Empty); - tokenArray[arrayIndex + 6] = new XSigSerialToken(stringIndex + 6, String.Empty); + tokenArray[arrayIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); + tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); + tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); + tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); + tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); + tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); arrayIndex += offset; stringIndex += maxStrings; From 70d2633eb0be310fe06fd4571b68cd667a563b25 Mon Sep 17 00:00:00 2001 From: Jason Alborough Date: Thu, 20 Oct 2022 09:52:58 -0400 Subject: [PATCH 146/202] fix: max number of presets now uses join span rather than join start. --- .../Essentials Devices Common/Cameras/CameraBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs index 1ef679ba..c5758108 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs @@ -223,7 +223,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist); - for (int i = 0; i < joinMap.NumberOfPresets.JoinNumber; i++) + for (int i = 0; i < joinMap.NumberOfPresets.JoinSpan; i++) { int tempNum = i; From 53596040987fcfb834e298bfc1ce72e7f539205c Mon Sep 17 00:00:00 2001 From: jdevito Date: Thu, 20 Oct 2022 11:11:07 -0500 Subject: [PATCH 147/202] fix: added bool property tracking if meeting is require, added poll method and updated GetBookings to reference bool property that prohibits polling when meeting password is required --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 30ec50c8..96d966f4 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -66,6 +66,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private readonly ZoomRoomPropertiesConfig _props; + private bool _meetingPasswordRequired; + + public void Poll(string pollString) + { + if(_meetingPasswordRequired) return; + + SendText(string.Format("{0}{1}", pollString, SendDelimiter)); + } + public ZoomRoom(DeviceConfig config, IBasicCommunication comm) : base(config) { @@ -79,13 +88,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (_props.CommunicationMonitorProperties != null) { - CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, - _props.CommunicationMonitorProperties); + CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, _props.CommunicationMonitorProperties.PollInterval, _props.CommunicationMonitorProperties.TimeToWarning, _props.CommunicationMonitorProperties.TimeToError, + () => Poll(_props.CommunicationMonitorProperties.PollString)); } else { - CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, - "zStatus SystemUnit" + SendDelimiter); + CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, () => Poll("zStatus SystemUnit")); } DeviceManager.AddDevice(CommunicationMonitor); @@ -1985,6 +1993,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// private void GetBookings() { + if (_meetingPasswordRequired) return; + SendText("zCommand Bookings List"); } @@ -2170,6 +2180,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom ); } + _meetingPasswordRequired = false; base.OnCallStatusChange(item); Debug.Console(1, this, "[OnCallStatusChange] Current Call Status: {0}", @@ -3390,6 +3401,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var handler = PasswordRequired; if (handler != null) { + if(!loginFailed || !loginCancelled) + _meetingPasswordRequired = true; + handler(this, new PasswordPromptEventArgs(lastAttemptIncorrect, loginFailed, loginCancelled, message)); } } From 578754de8530bf412259f02d0f15c97d7c84a409 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Thu, 20 Oct 2022 13:09:32 -0500 Subject: [PATCH 148/202] feat: Added new folder program/joinmaps feat: added new console command to write markdown for joinmap data and save to file --- PepperDashEssentials/ControlSystem.cs | 28 +++-- .../Bridges/BridgeBase.cs | 59 ++++++++- .../JoinMaps/JoinMapBase.cs | 114 +++++++++++++++++- 3 files changed, 189 insertions(+), 12 deletions(-) diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index dd8f3d5a..aba3b50a 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -83,10 +83,10 @@ namespace PepperDash.Essentials CrestronConsole.AddNewConsoleCommand(BridgeHelper.PrintJoinMap, "getjoinmap", "map(s) for bridge or device on bridge [brKey [devKey]]", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => - { - Debug.Console(0, Debug.ErrorLogLevel.Notice, "CONSOLE MESSAGE: {0}", s); - }, "appdebugmessage", "Writes message to log", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(BridgeHelper.JoinmapMarkdown, "getjoinmapmarkdown" + , "generate markdown of map(s) for bridge or device on bridge [brKey [devKey]]", ConsoleAccessLevelEnum.AccessOperator); + + CrestronConsole.AddNewConsoleCommand(s => Debug.Console(0, Debug.ErrorLogLevel.Notice, "CONSOLE MESSAGE: {0}", s), "appdebugmessage", "Writes message to log", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(s => { @@ -103,12 +103,16 @@ namespace PepperDash.Essentials (ConfigReader.ConfigObject, Newtonsoft.Json.Formatting.Indented)); }, "showconfig", "Shows the current running merged config", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => - { - CrestronConsole.ConsoleCommandResponse("This system can be found at the following URLs:\r\n" + - "System URL: {0}\r\n" + - "Template URL: {1}", ConfigReader.ConfigObject.SystemUrl, ConfigReader.ConfigObject.TemplateUrl); - }, "portalinfo", "Shows portal URLS from configuration", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => + CrestronConsole.ConsoleCommandResponse( + "This system can be found at the following URLs:\r\n" + + "System URL: {0}\r\n" + + "Template URL: {1}", + ConfigReader.ConfigObject.SystemUrl, + ConfigReader.ConfigObject.TemplateUrl), + "portalinfo", + "Shows portal URLS from configuration", + ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(DeviceManager.GetRoutingPorts, @@ -296,6 +300,10 @@ namespace PepperDash.Essentials if (!Directory.Exists(pluginDir)) Directory.Create(pluginDir); + var joinmapDir = Global.FilePathPrefix + "joinmaps"; + if(!Directory.Exists(joinmapDir)) + Directory.Create(joinmapDir); + return configExists; } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs index a1326770..65a1c35d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs @@ -46,6 +46,33 @@ namespace PepperDash.Essentials.Core.Bridges bridge.PrintJoinMaps(); } } + public static void JoinmapMarkdown(string command) + { + var targets = command.Split(' '); + + var bridgeKey = targets[0].Trim(); + + var bridge = DeviceManager.GetDeviceForKey(bridgeKey) as EiscApiAdvanced; + + if (bridge == null) + { + Debug.Console(0, "Unable to find advanced bridge with key: '{0}'", bridgeKey); + return; + } + + if (targets.Length > 1) + { + var deviceKey = targets[1].Trim(); + + if (string.IsNullOrEmpty(deviceKey)) return; + bridge.MarkdownJoinMapForDevice(deviceKey, bridgeKey); + } + else + { + bridge.MarkdownForBridge(bridgeKey); + + } + } } @@ -227,6 +254,19 @@ namespace PepperDash.Essentials.Core.Bridges joinMap.Value.PrintJoinMapInfo(); } } + /// + /// Generates markdown for all join maps on this bridge + /// + public virtual void MarkdownForBridge(string bridgeKey) + { + Debug.Console(0, this, "Writing Joinmaps to files for EISC IPID: {0}", Eisc.ID.ToString("X")); + + foreach (var joinMap in JoinMaps) + { + Debug.Console(0, "Generating markdown for device '{0}':", joinMap.Key); + joinMap.Value.MarkdownJoinMapInfo(joinMap.Key, bridgeKey); + } + } /// /// Prints the join map for a device by key @@ -242,9 +282,26 @@ namespace PepperDash.Essentials.Core.Bridges return; } - Debug.Console(0, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key); + Debug.Console(0, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key); joinMap.PrintJoinMapInfo(); } + /// + /// Prints the join map for a device by key + /// + /// + public void MarkdownJoinMapForDevice(string deviceKey, string bridgeKey) + { + var joinMap = JoinMaps[deviceKey]; + + if (joinMap == null) + { + Debug.Console(0, this, "Unable to find joinMap for device with key: '{0}'", deviceKey); + return; + } + + Debug.Console(0, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key); + joinMap.MarkdownJoinMapInfo(deviceKey, bridgeKey); + } /// /// Used for debugging to trigger an action based on a join number and type diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs index 04abc7f8..d41e0432 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs @@ -2,7 +2,10 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; +using System.Text; using Crestron.SimplSharp.Reflection; +using Crestron.SimplSharp.CrestronIO; +using Crestron.SimplSharp; using PepperDash.Core; using PepperDash.Essentials.Core.Config; @@ -256,12 +259,64 @@ namespace PepperDash.Essentials.Core var analogs = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value); Debug.Console(2, "Found {0} Analog Joins", analogs.Count); PrintJoinList(GetSortedJoins(analogs)); - + Debug.Console(0, "Serials:"); var serials = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value); Debug.Console(2, "Found {0} Serial Joins", serials.Count); PrintJoinList(GetSortedJoins(serials)); + } + /// + /// Prints the join information to console + /// + public void MarkdownJoinMapInfo(string deviceKey, string bridgeKey) + { + var pluginType = GetType().Name; + + Debug.Console(0, "{0}:\n", pluginType); + + var sb = new StringBuilder(); + + sb.AppendLine(String.Format("# {0}", GetType().Name)); + sb.AppendLine(String.Format("Generated from '{0}' on bridge '{1}'", deviceKey, bridgeKey)); + sb.AppendLine(); + sb.AppendLine("## Digitals"); + // Get the joins of each type and print them + var digitals = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Digital) == eJoinType.Digital).ToDictionary(j => j.Key, j => j.Value); + Debug.Console(2, "Found {0} Digital Joins", digitals.Count); + var digitalSb = AppendJoinList(GetSortedJoins(digitals)); + digitalSb.AppendLine("## Analogs"); + digitalSb.AppendLine(); + + Debug.Console(0, "Analogs:"); + var analogs = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value); + Debug.Console(2, "Found {0} Analog Joins", analogs.Count); + var analogSb = AppendJoinList(GetSortedJoins(analogs)); + analogSb.AppendLine("## Serials"); + analogSb.AppendLine(); + + Debug.Console(0, "Serials:"); + var serials = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value); + Debug.Console(2, "Found {0} Serial Joins", serials.Count); + var serialSb = AppendJoinList(GetSortedJoins(serials)); + + sb.EnsureCapacity(sb.Length + digitalSb.Length + analogSb.Length + serialSb.Length); + sb.Append(digitalSb).Append(analogSb).Append(serialSb); + + WriteJoinmapMarkdown(sb, pluginType, bridgeKey, deviceKey); + + } + + private static void WriteJoinmapMarkdown(StringBuilder stringBuilder, string pluginType, string bridgeKey, string deviceKey) + { + var fileName = String.Format("{0}{1}{2}__{3}__{4}.md", Global.FilePathPrefix, "joinMaps/", pluginType, bridgeKey, deviceKey); + + using (var sw = new StreamWriter(fileName)) + { + sw.WriteLine(stringBuilder.ToString()); + Debug.Console(0, "Joinmap Readme generated and written to {0}", fileName); + } + } /// @@ -293,6 +348,63 @@ namespace PepperDash.Essentials.Core } } + static StringBuilder AppendJoinList(List> joins) + { + var sb = new StringBuilder(); + const string stringFormatter = "| {0} | {1} | {2} | {3} | {4} |"; + const int joinNumberLen = 11; + const int joinSpanLen = 9; + const int typeLen = 19; + const int capabilitiesLen = 12; + var descriptionLen = (from @join in joins + select String.IsNullOrEmpty(@join.Value.AttributeName) + ? @join.Value.Metadata.Description + : @join.Value.AttributeName into description + select description.Length) + .Concat(new[] { 11 }).Max(); + + var joinNumberHeader = String.Format("Join Number").PadRight(joinNumberLen, ' '); + var joinSpanHeader = String.Format("Join Span").PadRight(joinSpanLen, ' '); + var descriptionHeader = String.Format("Description").PadRight(descriptionLen, ' '); + var typeHeader = String.Format("Type").PadRight(typeLen, ' '); + var capabilitiesHeader = String.Format("Capabilities").PadRight(capabilitiesLen, ' '); + //build header + sb.AppendLine(String.Format(stringFormatter, + joinNumberHeader, + joinSpanHeader, + descriptionHeader, + typeHeader, + capabilitiesHeader)); + //build table seperator + sb.AppendLine(String.Format(stringFormatter, + new String('-', joinNumberLen), + new String('-', joinSpanLen), + new String('-', descriptionLen), + new String('-', typeLen), + new String('-', capabilitiesLen))); + + foreach (var join in joins) + { + var joinNumber = String.Format("{0}", join.Value.JoinNumber).PadRight(joinNumberLen, ' '); + var joinSpan = String.Format("{0}", join.Value.JoinSpan).PadRight(joinSpanLen); + var joinDescription = String.Format(String.IsNullOrEmpty(join.Value.AttributeName) + ? join.Value.Metadata.Description + : join.Value.AttributeName).PadRight(descriptionLen, ' '); + var joinType = String.Format("{0}", join.Value.Metadata.JoinType.ToString()).PadRight(typeLen, ' '); + var joinCapabilities = + String.Format("{0}", join.Value.Metadata.JoinCapabilities.ToString()).PadRight(capabilitiesLen, ' '); + + sb.AppendLine(String.Format("| {0} | {1} | {2} | {3} | {4} |", + joinNumber, + joinSpan, + joinDescription, + joinType, + joinCapabilities)); + } + sb.AppendLine(); + return sb; + } + /// /// Attempts to find the matching key for the custom join and if found overwrites the default JoinData with the custom /// From fea3189a18933648cbd2604f39d6e2bb327042ad Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 21 Oct 2022 16:20:14 -0500 Subject: [PATCH 149/202] refactor: moved markdown method inside join data feat: proper error handling --- .../Extensions/StringExtensions.cs | 4 + .../JoinMaps/JoinMapBase.cs | 113 +++++++++++------- 2 files changed, 72 insertions(+), 45 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs index 708ed930..39501387 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs @@ -16,5 +16,9 @@ namespace PepperDash.Essentials.Core { return string.IsNullOrEmpty(s.Trim()) ? null : s; } + public static string ReplaceIfNullOrEmpty(this string s, string newString) + { + return string.IsNullOrEmpty(s) ? newString : s; + } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs index d41e0432..6ffb16cc 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Data; +using System.Globalization; using System.Linq; using System.Runtime.InteropServices; using System.Text; @@ -196,19 +198,6 @@ namespace PepperDash.Essentials.Core protected void AddJoins(Type type) { - // Add all the JoinDataComplete properties to the Joins Dictionary and pass in the offset - //Joins = this.GetType() - // .GetCType() - // .GetFields(BindingFlags.Public | BindingFlags.Instance) - // .Where(field => field.IsDefined(typeof(JoinNameAttribute), true)) - // .Select(field => (JoinDataComplete)field.GetValue(this)) - // .ToDictionary(join => join.GetNameAttribute(), join => - // { - // join.SetJoinOffset(_joinOffset); - // return join; - // }); - - //type = this.GetType(); <- this wasn't working because 'this' was always the base class, never the derived class var fields = type.GetCType() .GetFields(BindingFlags.Public | BindingFlags.Instance) @@ -222,7 +211,7 @@ namespace PepperDash.Essentials.Core if (value == null) { - Debug.Console(0, "Unable to caset base class to {0}", type.Name); + Debug.Console(0, "Unable to cast base class to {0}", type.Name); continue; } @@ -356,25 +345,15 @@ namespace PepperDash.Essentials.Core const int joinSpanLen = 9; const int typeLen = 19; const int capabilitiesLen = 12; - var descriptionLen = (from @join in joins - select String.IsNullOrEmpty(@join.Value.AttributeName) - ? @join.Value.Metadata.Description - : @join.Value.AttributeName into description - select description.Length) - .Concat(new[] { 11 }).Max(); + var descriptionLen = (from @join in joins select @join.Value into j select j.Metadata.Description.Length).Concat(new[] {11}).Max(); - var joinNumberHeader = String.Format("Join Number").PadRight(joinNumberLen, ' '); - var joinSpanHeader = String.Format("Join Span").PadRight(joinSpanLen, ' '); - var descriptionHeader = String.Format("Description").PadRight(descriptionLen, ' '); - var typeHeader = String.Format("Type").PadRight(typeLen, ' '); - var capabilitiesHeader = String.Format("Capabilities").PadRight(capabilitiesLen, ' '); //build header sb.AppendLine(String.Format(stringFormatter, - joinNumberHeader, - joinSpanHeader, - descriptionHeader, - typeHeader, - capabilitiesHeader)); + String.Format("Join Number").PadRight(joinNumberLen, ' '), + String.Format("Join Span").PadRight(joinSpanLen, ' '), + String.Format("Description").PadRight(descriptionLen, ' '), + String.Format("Type").PadRight(typeLen, ' '), + String.Format("Capabilities").PadRight(capabilitiesLen, ' '))); //build table seperator sb.AppendLine(String.Format(stringFormatter, new String('-', joinNumberLen), @@ -385,21 +364,7 @@ namespace PepperDash.Essentials.Core foreach (var join in joins) { - var joinNumber = String.Format("{0}", join.Value.JoinNumber).PadRight(joinNumberLen, ' '); - var joinSpan = String.Format("{0}", join.Value.JoinSpan).PadRight(joinSpanLen); - var joinDescription = String.Format(String.IsNullOrEmpty(join.Value.AttributeName) - ? join.Value.Metadata.Description - : join.Value.AttributeName).PadRight(descriptionLen, ' '); - var joinType = String.Format("{0}", join.Value.Metadata.JoinType.ToString()).PadRight(typeLen, ' '); - var joinCapabilities = - String.Format("{0}", join.Value.Metadata.JoinCapabilities.ToString()).PadRight(capabilitiesLen, ' '); - - sb.AppendLine(String.Format("| {0} | {1} | {2} | {3} | {4} |", - joinNumber, - joinSpan, - joinDescription, - joinType, - joinCapabilities)); + sb.AppendLine(join.Value.GetMarkdownFormattedData(stringFormatter, descriptionLen)); } sb.AppendLine(); return sb; @@ -571,6 +536,64 @@ namespace PepperDash.Essentials.Core Metadata = metadata; } + public string GetMarkdownFormattedData(string stringFormatter, int descriptionLen) + { + + //Fixed Width Headers + var joinNumberLen = String.Format("Join Number").Length; + var joinSpanLen = String.Format("Join Span").Length; + var typeLen = String.Format("AnalogDigitalSerial").Length; + var capabilitiesLen = String.Format("ToFromFusion").Length; + + //Track which one failed, if it did + const string placeholder = "unknown"; + var dataArray = new Dictionary + { + {"joinNumber", placeholder.PadRight(joinNumberLen, ' ')}, + {"joinSpan", placeholder.PadRight(joinSpanLen, ' ')}, + {"description", placeholder.PadRight(descriptionLen, ' ')}, + {"joinType", placeholder.PadRight(typeLen, ' ')}, + {"capabilities", placeholder.PadRight(capabilitiesLen, ' ')} + }; + + + try + { + dataArray["joinNumber"] = String.Format("{0}", JoinNumber.ToString(CultureInfo.InvariantCulture).ReplaceIfNullOrEmpty(placeholder)).PadRight(joinNumberLen, ' '); + dataArray["joinSpan"] = String.Format("{0}", JoinSpan.ToString(CultureInfo.InvariantCulture).ReplaceIfNullOrEmpty(placeholder)).PadRight(joinSpanLen, ' '); + dataArray["description"] = String.Format("{0}", Metadata.Description.ReplaceIfNullOrEmpty(placeholder)).PadRight(descriptionLen, ' '); + dataArray["joinType"] = String.Format("{0}", Metadata.JoinType.ToString().ReplaceIfNullOrEmpty(placeholder)).PadRight(typeLen, ' '); + dataArray["capabilities"] = String.Format("{0}", Metadata.JoinCapabilities.ToString().ReplaceIfNullOrEmpty(placeholder)).PadRight(capabilitiesLen, ' '); + + return String.Format(stringFormatter, + dataArray["joinNumber"], + dataArray["joinSpan"], + dataArray["description"], + dataArray["joinType"], + dataArray["capabilities"]); + + } + catch (Exception e) + { + //Don't Throw - we don't want to kill the system if this falls over - it's not mission critical. Print the error, use placeholder data + var errorKey = string.Empty; + foreach (var item in dataArray) + { + if (item.Value.TrimEnd() == placeholder) ; + errorKey = item.Key; + break; + } + Debug.Console(0, "Unable to decode join metadata {1}- {0}", e.Message, !String.IsNullOrEmpty(errorKey) ? (' ' + errorKey) : String.Empty); + return String.Format(stringFormatter, + dataArray["joinNumber"], + dataArray["joinSpan"], + dataArray["description"], + dataArray["joinType"], + dataArray["capabilities"]); + } + } + + /// /// Sets the join offset value /// From bef07fe41bf335d2271a1b1b21e664533f983ed9 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 25 Oct 2022 10:30:02 -0600 Subject: [PATCH 150/202] fix(essentials): Block all commands to ZoomRoom on incoming call --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 6f497cef..5d63a4cf 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -64,9 +64,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private bool _meetingPasswordRequired; + private bool _waitingForUserToAcceptOrRejectIncomingCall; + public void Poll(string pollString) { - if(_meetingPasswordRequired) return; + if(_meetingPasswordRequired || _waitingForUserToAcceptOrRejectIncomingCall) return; SendText(string.Format("{0}{1}", pollString, SendDelimiter)); } @@ -968,6 +970,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void SendText(string command) { + if (_meetingPasswordRequired) + { + Debug.Console(2, this, "Blocking commands to ZoomRoom while waiting for user to enter meeting password"); + return; + } + + if (_waitingForUserToAcceptOrRejectIncomingCall) + { + Debug.Console(2, this, "Blocking commands to ZoomRoom while waiting for user to accept or reject incoming call"); + return; + } + if (CommDebuggingIsOn) { Debug.Console(1, this, "Sending: '{0}'", command); @@ -1592,6 +1606,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Id = incomingCall.callerJID }; + _waitingForUserToAcceptOrRejectIncomingCall = true; + ActiveCalls.Add(newCall); OnCallStatusChange(newCall); @@ -1618,6 +1634,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom OnCallStatusChange(existingCall); } + _waitingForUserToAcceptOrRejectIncomingCall = false; + UpdateCallStatus(); } @@ -2000,7 +2018,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// private void GetBookings() { - if (_meetingPasswordRequired) return; + if (_meetingPasswordRequired || _waitingForUserToAcceptOrRejectIncomingCall) return; SendText("zCommand Bookings List"); } @@ -2637,6 +2655,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void AcceptCall() { + _waitingForUserToAcceptOrRejectIncomingCall = false; + var incomingCall = ActiveCalls.FirstOrDefault( c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); @@ -2646,6 +2666,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public override void AcceptCall(CodecActiveCallItem call) { + _waitingForUserToAcceptOrRejectIncomingCall = false; + SendText(string.Format("zCommand Call Accept callerJID: {0}", call.Id)); call.Status = eCodecCallStatus.Connected; @@ -2657,6 +2679,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void RejectCall() { + _waitingForUserToAcceptOrRejectIncomingCall = false; + var incomingCall = ActiveCalls.FirstOrDefault( c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); @@ -2666,6 +2690,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public override void RejectCall(CodecActiveCallItem call) { + _waitingForUserToAcceptOrRejectIncomingCall = false; + SendText(string.Format("zCommand Call Reject callerJID: {0}", call.Id)); call.Status = eCodecCallStatus.Disconnected; @@ -3451,9 +3477,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void SubmitPassword(string password) { + _meetingPasswordRequired = false; Debug.Console(2, this, "Password Submitted: {0}", password); Dial(_lastDialedMeetingNumber, password); - //OnPasswordRequired(false, false, true, ""); } void OnPasswordRequired(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) From 4d6da37c60b39e076f7056403c30741b60dbee22 Mon Sep 17 00:00:00 2001 From: jdevito Date: Fri, 28 Oct 2022 08:38:16 -0500 Subject: [PATCH 151/202] fix: added additional evaluations for prompt property tracking and set/reset to handled unknown user scenarios --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 5d63a4cf..60965ca0 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2578,11 +2578,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom PasswordRequired += (devices, args) => { - Debug.Console(0, this, "***********************************PaswordRequired. Message: {0} Cancelled: {1} Last Incorrect: {2} Failed: {3}", args.Message, args.LoginAttemptCancelled, args.LastAttemptWasIncorrect, args.LoginAttemptFailed); + Debug.Console(2, this, "***********************************PaswordRequired. Message: {0} Cancelled: {1} Last Incorrect: {2} Failed: {3}", args.Message, args.LoginAttemptCancelled, args.LastAttemptWasIncorrect, args.LoginAttemptFailed); if (args.LoginAttemptCancelled) { trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, false); + _meetingPasswordRequired = false; return; } @@ -2594,6 +2595,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (args.LoginAttemptFailed) { // login attempt failed + _meetingPasswordRequired = false; return; } @@ -2818,16 +2820,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void LeaveMeeting() { - SendText("zCommand Call Leave"); + if (_meetingPasswordRequired) _meetingPasswordRequired = false; + if (_waitingForUserToAcceptOrRejectIncomingCall) _waitingForUserToAcceptOrRejectIncomingCall = false; + + SendText("zCommand Call Leave"); } public override void EndCall(CodecActiveCallItem call) { + if (_meetingPasswordRequired) _meetingPasswordRequired = false; + if (_waitingForUserToAcceptOrRejectIncomingCall) _waitingForUserToAcceptOrRejectIncomingCall = false; + SendText("zCommand Call Disconnect"); } public override void EndAllCalls() { + if (_meetingPasswordRequired) _meetingPasswordRequired = false; + if (_waitingForUserToAcceptOrRejectIncomingCall) _waitingForUserToAcceptOrRejectIncomingCall = false; + SendText("zCommand Call Disconnect"); } @@ -3487,10 +3498,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom var handler = PasswordRequired; if (handler != null) { - if(!loginFailed || !loginCancelled) - _meetingPasswordRequired = true; - - handler(this, new PasswordPromptEventArgs(lastAttemptIncorrect, loginFailed, loginCancelled, message)); + _meetingPasswordRequired = !loginFailed || !loginCancelled; + Debug.Console(2, this, "Meeting Password Required: {0}", _meetingPasswordRequired); + + handler(this, new PasswordPromptEventArgs(lastAttemptIncorrect, loginFailed, loginCancelled, message)); } } From a09212417c7dcaadf6f1cd499828a62963c2792a Mon Sep 17 00:00:00 2001 From: jdevito Date: Fri, 28 Oct 2022 16:20:49 -0500 Subject: [PATCH 152/202] fix: removed property sets as recommended in discussion; removed 'if' statements before property sets in leave and end call methods --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 60965ca0..cc0dfcd7 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2583,7 +2583,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (args.LoginAttemptCancelled) { trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, false); - _meetingPasswordRequired = false; return; } @@ -2595,7 +2594,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom if (args.LoginAttemptFailed) { // login attempt failed - _meetingPasswordRequired = false; return; } @@ -2820,24 +2818,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void LeaveMeeting() { - if (_meetingPasswordRequired) _meetingPasswordRequired = false; - if (_waitingForUserToAcceptOrRejectIncomingCall) _waitingForUserToAcceptOrRejectIncomingCall = false; - + _meetingPasswordRequired = false; + _waitingForUserToAcceptOrRejectIncomingCall = false; + SendText("zCommand Call Leave"); } public override void EndCall(CodecActiveCallItem call) { - if (_meetingPasswordRequired) _meetingPasswordRequired = false; - if (_waitingForUserToAcceptOrRejectIncomingCall) _waitingForUserToAcceptOrRejectIncomingCall = false; + _meetingPasswordRequired = false; + _waitingForUserToAcceptOrRejectIncomingCall = false; SendText("zCommand Call Disconnect"); } public override void EndAllCalls() { - if (_meetingPasswordRequired) _meetingPasswordRequired = false; - if (_waitingForUserToAcceptOrRejectIncomingCall) _waitingForUserToAcceptOrRejectIncomingCall = false; + _meetingPasswordRequired = false; + _waitingForUserToAcceptOrRejectIncomingCall = false; SendText("zCommand Call Disconnect"); } From 6f9a9ee255c6d90d98680474a1e5c2df3b79fa70 Mon Sep 17 00:00:00 2001 From: jdevito Date: Fri, 28 Oct 2022 16:47:43 -0500 Subject: [PATCH 153/202] fix: moved setting set in event before null check --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index cc0dfcd7..abf308d9 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -3493,10 +3493,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom void OnPasswordRequired(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) { + _meetingPasswordRequired = !loginFailed || !loginCancelled; + var handler = PasswordRequired; if (handler != null) - { - _meetingPasswordRequired = !loginFailed || !loginCancelled; + { Debug.Console(2, this, "Meeting Password Required: {0}", _meetingPasswordRequired); handler(this, new PasswordPromptEventArgs(lastAttemptIncorrect, loginFailed, loginCancelled, message)); From 60afe203dd8f19508a2955ffb60e6443de60615b Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 2 Nov 2022 09:18:20 -0500 Subject: [PATCH 154/202] fix: XSig Fixes --- .../VideoCodec/VideoCodecBase.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 44d3f423..19c61b9f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1393,11 +1393,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, call.IsOnHold); //serials - tokenArray[arrayIndex] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); - tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 2, call.Number ?? String.Empty); - tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString()); - tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 4, call.Type.ToString()); - tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 5, call.Status.ToString()); + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, call.Number ?? String.Empty); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString()); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, call.Type.ToString()); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, call.Status.ToString()); if(call.Duration != null) { // May need to verify correct string format here @@ -1417,12 +1417,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //serials - tokenArray[arrayIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); - tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); - tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); - tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); - tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); - tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); + tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); arrayIndex += offset; stringIndex += maxStrings; From 2be42f88bc8179987c5c9868ca54cd81e776027a Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 4 Nov 2022 09:48:17 -0600 Subject: [PATCH 155/202] chore: update PD Core version In order to fix issues with debug file location for VC-4, the PD Core version needs to be updated --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index 4c411add..04d36492 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From ce51a62d9734a1fd4efdef666e107f6a49fd037e Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 4 Nov 2022 14:01:11 -0600 Subject: [PATCH 156/202] chore: update PD Core version --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index 04d36492..41e00961 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From fc3840173e0005f323a8659d839a8053aa79e25f Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 8 Nov 2022 08:44:39 -0700 Subject: [PATCH 157/202] chore: Update PD Core version --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index 41e00961..3a15ad08 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From c07f52b06f36960d7dde335b26903007b78ddd38 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 10 Nov 2022 12:51:04 -0700 Subject: [PATCH 158/202] feat: update VC-4 client to use correct RoomID --- .../Bridges/BridgeBase.cs | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs index a1326770..7bb25b0a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs @@ -394,35 +394,45 @@ namespace PepperDash.Essentials.Core.Bridges var controlProperties = CommFactory.GetControlPropertiesConfig(dc); + BasicTriList eisc; + switch (dc.Type.ToLower()) { case "eiscapiadv": case "eiscapiadvanced": { - var eisc = new ThreeSeriesTcpIpEthernetIntersystemCommunications(controlProperties.IpIdInt, + eisc = new ThreeSeriesTcpIpEthernetIntersystemCommunications(controlProperties.IpIdInt, controlProperties.TcpSshProperties.Address, Global.ControlSystem); - return new EiscApiAdvanced(dc, eisc); + break; } case "eiscapiadvancedserver": { - var eisc = new EISCServer(controlProperties.IpIdInt, Global.ControlSystem); - return new EiscApiAdvanced(dc, eisc); + eisc = new EISCServer(controlProperties.IpIdInt, Global.ControlSystem); + break; } case "eiscapiadvancedclient": { - var eisc = new EISCClient(controlProperties.IpIdInt, controlProperties.TcpSshProperties.Address, Global.ControlSystem); - return new EiscApiAdvanced(dc, eisc); + eisc = new EISCClient(controlProperties.IpIdInt, controlProperties.TcpSshProperties.Address, Global.ControlSystem); + break; } case "vceiscapiadv": case "vceiscapiadvanced": { - var eisc = new VirtualControlEISCClient(controlProperties.IpIdInt, InitialParametersClass.RoomId, + eisc = new VirtualControlEISCClient(controlProperties.IpIdInt, controlProperties.RoomId, Global.ControlSystem); - return new EiscApiAdvanced(dc, eisc); + break; } default: - return null; + eisc = null; + break; } + + if (eisc == null) + { + return null; + } + + return new EiscApiAdvanced(dc, eisc); } } From db19da124cdb53921e1e3e82db5c8894f236b5fd Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 11 Nov 2022 14:37:46 -0700 Subject: [PATCH 159/202] fix: set debug level to 2 on startup Some plugins and devices are doing their own filtering based on the debug level that's normally set using the `appdebug` console command. On VC-4, there's no way to set that value. With this change, when Essentials starts on a server, the debug level will be set to 2, so that any of the messages that might be filtered based on the debug level won't be filtered. --- PepperDashEssentials/ControlSystem.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index dd8f3d5a..9a48000a 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -195,6 +195,8 @@ namespace PepperDash.Essentials } else // Handles Linux OS (Virtual Control) { + Debug.SetDebugLevel(2); + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on Virtual Control Server", Global.AssemblyVersion); // Set path to User/ From 5e797db0965e1be9a3f001f91624d8ac816e3921 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 11 Nov 2022 16:26:37 -0700 Subject: [PATCH 160/202] fix: add check for missing/empty roomId --- .../PepperDashEssentialsBase/Bridges/BridgeBase.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs index 7bb25b0a..252c9c48 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs @@ -418,6 +418,12 @@ namespace PepperDash.Essentials.Core.Bridges case "vceiscapiadv": case "vceiscapiadvanced": { + if (string.IsNullOrEmpty(controlProperties.RoomId)) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to build VC-4 EISC Client for device {0}. Room ID is missing or empty", dc.Key); + eisc = null; + break; + } eisc = new VirtualControlEISCClient(controlProperties.IpIdInt, controlProperties.RoomId, Global.ControlSystem); break; From 247827ac2580a64cd84431f39c6ea07d915e1549 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Mon, 14 Nov 2022 10:10:22 -0600 Subject: [PATCH 161/202] fix: UpdateCallStatusXsig() now properly refreshing calls --- .../VideoCodec/VideoCodecBase.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 44d3f423..19c61b9f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1393,11 +1393,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, call.IsOnHold); //serials - tokenArray[arrayIndex] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); - tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 2, call.Number ?? String.Empty); - tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString()); - tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 4, call.Type.ToString()); - tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 5, call.Status.ToString()); + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, call.Number ?? String.Empty); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString()); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, call.Type.ToString()); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, call.Status.ToString()); if(call.Duration != null) { // May need to verify correct string format here @@ -1417,12 +1417,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //serials - tokenArray[arrayIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); - tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); - tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); - tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); - tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); - tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); + tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); arrayIndex += offset; stringIndex += maxStrings; From ba0bae3c4ecf07ad7d9bcce1636cf1181b3d1c37 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 16 Nov 2022 10:51:48 -0700 Subject: [PATCH 162/202] chore: update PD Core to 1.1.3 --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index 3a15ad08..e2f8b03b 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From 1b43fba37e2a38bd275fac585a80d478a442c442 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 21 Nov 2022 10:28:08 -0700 Subject: [PATCH 163/202] fix: add logic to prevent vacancy from triggering room off if room is in a call --- .../Room/Types/EssentialsHuddleVtc1Room.cs | 18 ++++++++++++++++++ .../Room/EssentialsRoomBase.cs | 16 ++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index e622983f..0b7b2b28 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -745,6 +745,24 @@ namespace PepperDash.Essentials { //Implement this } + + protected override bool AllowVacancyTimerToStart() + { + bool allowVideo = true; + bool allowAudio = true; + + if (VideoCodec != null) + { + allowVideo = !VideoCodec.IsInCall; + } + + if (AudioCodec != null) + { + allowAudio = !AudioCodec.IsInCall; + } + + return allowVideo && allowAudio; + } /// /// Does what it says diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs index 352cbfcd..6cb06841 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs @@ -343,7 +343,7 @@ namespace PepperDash.Essentials.Core void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e) { - if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false) + if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false && AllowVacancyTimerToStart()) { Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Vacancy Detected"); // Trigger the timer when the room is vacant @@ -361,7 +361,19 @@ namespace PepperDash.Essentials.Core /// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed /// /// - public abstract void RoomVacatedForTimeoutPeriod(object o); + public abstract void RoomVacatedForTimeoutPeriod(object o) + { + + } + + /// + /// Allow the vacancy event from an occupancy sensor to turn the room off. + /// + /// If the timer should be allowed. Defaults to true + protected virtual bool AllowVacancyTimerToStart() + { + return true; + } } /// From a2b67798f3bb3de1e5a6a9279ea7bfa838c14f67 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 21 Nov 2022 10:37:26 -0700 Subject: [PATCH 164/202] refactor: add logging statements --- PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index 0b7b2b28..038acd9d 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -753,14 +753,18 @@ namespace PepperDash.Essentials if (VideoCodec != null) { + Debug.Console(2,this, Debug.ErrorLogLevel.Notice, "Room {0} is in a video call. Not allowing auto power off", Key); allowVideo = !VideoCodec.IsInCall; } if (AudioCodec != null) { + Debug.Console(2,this, Debug.ErrorLogLevel.Notice, "Room {0} is in an audio call. Not allowing auto power off", Key); allowAudio = !AudioCodec.IsInCall; } + Debug.Console(2, this, "Room {0} allowing vacancy timer to start: {1}", Key, allowVideo && allowAudio); + return allowVideo && allowAudio; } From 5263b16bb7f7ab30b4abd233bfcbab7ba2561e2c Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 21 Nov 2022 10:42:33 -0700 Subject: [PATCH 165/202] refactor: fix issues with log statments --- PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index 038acd9d..d04de3cc 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -753,13 +753,13 @@ namespace PepperDash.Essentials if (VideoCodec != null) { - Debug.Console(2,this, Debug.ErrorLogLevel.Notice, "Room {0} is in a video call. Not allowing auto power off", Key); + Debug.Console(2,this, Debug.ErrorLogLevel.Notice, "Room {0} {1} in a video call", Key, VideoCodec.IsInCall ? "is" : "is not"); allowVideo = !VideoCodec.IsInCall; } if (AudioCodec != null) { - Debug.Console(2,this, Debug.ErrorLogLevel.Notice, "Room {0} is in an audio call. Not allowing auto power off", Key); + Debug.Console(2,this, Debug.ErrorLogLevel.Notice, "Room {0} {1} in an audio call", Key, AudioCodec.IsInCall ? "is" : "is not"); allowAudio = !AudioCodec.IsInCall; } From 430612847443b0eb07a5b271be116a606da8d0b3 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 21 Nov 2022 10:45:25 -0700 Subject: [PATCH 166/202] refactor: fix abstract method --- .../PepperDashEssentialsBase/Room/EssentialsRoomBase.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs index 6cb06841..f5e3dee8 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs @@ -361,10 +361,7 @@ namespace PepperDash.Essentials.Core /// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed /// /// - public abstract void RoomVacatedForTimeoutPeriod(object o) - { - - } + public abstract void RoomVacatedForTimeoutPeriod(object o); /// /// Allow the vacancy event from an occupancy sensor to turn the room off. From 1b43b44d1914042f291213f835794c8e69a6ae16 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 23 Nov 2022 13:12:35 -0700 Subject: [PATCH 167/202] fix: typo in `TouchpanelBase` constructor The constructor was checking the wrong variable, leading to it always being null and failing to build the `EssentialsTouchpanelController` class. --- .../PepperDashEssentialsBase/UI/TouchpanelBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs index 36e0342e..7c64aa6d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs @@ -31,7 +31,7 @@ namespace PepperDash.Essentials.Core.UI :base(key, name) { - if (Panel == null) + if (panel == null) { Debug.Console(0, this, "Panel is not valid. Touchpanel class WILL NOT work correctly"); return; From 8e57e7ec31f9a2d9f6db5909538eaeb52aca62ff Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 23 Nov 2022 14:29:36 -0700 Subject: [PATCH 168/202] fix: add missing LoadSmartObjects call --- .../PepperDashEssentialsBase/UI/TouchpanelBase.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs index 7c64aa6d..c7be5048 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs @@ -71,6 +71,8 @@ namespace PepperDash.Essentials.Core.UI return; } } + + Panel.LoadSmartObjects(sgdName); }); AddPostActivationAction(() => From 042416b4705fac37673a8df63809bd0f8182405f Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 12 Dec 2022 10:01:14 -0700 Subject: [PATCH 169/202] chore: update PD Core version --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index e2f8b03b..b3c33396 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From 0ef8fcfd270c175bfd62c62927a7b06b3f6d176b Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 12 Dec 2022 11:42:16 -0700 Subject: [PATCH 170/202] chore: Update to PD Core 1.1.4 --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index b3c33396..ffea92a5 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From c2a439d20d2ce81a5c456bc883686cccbfc30b84 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 14 Dec 2022 09:47:31 -0600 Subject: [PATCH 171/202] feat: Add DinIo8 --- .../Crestron IO/DinIo8/DinIo8Controller.cs | 80 +++++++++++++++++++ .../PepperDash_Essentials_Core.csproj | 1 + 2 files changed, 81 insertions(+) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinIo8/DinIo8Controller.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinIo8/DinIo8Controller.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinIo8/DinIo8Controller.cs new file mode 100644 index 00000000..e3c2b094 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinIo8/DinIo8Controller.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.GeneralIO; +using PepperDash.Core; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Config; + +namespace PepperDash.Essentials.Core.CrestronIO +{ + public class DinIo8Controller:CrestronGenericBaseDevice, IIOPorts + { + private DinIo8 _device; + + public DinIo8Controller(string key, Func preActivationFunc, DeviceConfig config):base(key, config.Name) + { + AddPreActivationAction(() => + { + _device = preActivationFunc(config); + + RegisterCrestronGenericBase(_device); + }); + } + + #region Implementation of IIOPorts + + public CrestronCollection VersiPorts + { + get { return _device.VersiPorts; } + } + + public int NumberOfVersiPorts + { + get { return _device.NumberOfVersiPorts; } + } + + #endregion + + + } + + public class DinIo8ControllerFactory : EssentialsDeviceFactory + { + public DinIo8ControllerFactory() + { + TypeNames = new List() { "DinIo8" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new C2N-IO Device"); + + return new DinIo8Controller(dc.Key, GetDinIo8Device, dc); + } + + static DinIo8 GetDinIo8Device(DeviceConfig dc) + { + var control = CommFactory.GetControlPropertiesConfig(dc); + var cresnetId = control.CresnetIdInt; + var branchId = control.ControlPortNumber; + var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey; + + if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase)) + { + Debug.Console(0, "Device {0} is a valid cresnet master - creating new DinIo8", parentKey); + return new DinIo8(cresnetId, Global.ControlSystem); + } + var cresnetBridge = DeviceManager.GetDeviceForKey(parentKey) as IHasCresnetBranches; + + if (cresnetBridge != null) + { + Debug.Console(0, "Device {0} is a valid cresnet master - creating new DinIo8", parentKey); + return new DinIo8(cresnetId, cresnetBridge.CresnetBranches[branchId]); + } + Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey); + return null; + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index dfa59b88..351c781c 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -179,6 +179,7 @@ + From d980209bd89061a45c46432412a74e82a182a5d8 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 14 Dec 2022 11:43:44 -0600 Subject: [PATCH 172/202] Fixed Debug Statement to reflect proper device --- .../Crestron IO/DinIo8/DinIo8Controller.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinIo8/DinIo8Controller.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinIo8/DinIo8Controller.cs index e3c2b094..794fe609 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinIo8/DinIo8Controller.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinIo8/DinIo8Controller.cs @@ -49,7 +49,7 @@ namespace PepperDash.Essentials.Core.CrestronIO public override EssentialsDevice BuildDevice(DeviceConfig dc) { - Debug.Console(1, "Factory Attempting to create new C2N-IO Device"); + Debug.Console(1, "Factory Attempting to create new DinIo8 Device"); return new DinIo8Controller(dc.Key, GetDinIo8Device, dc); } From 81c779e595a619196c41be0563a20358182d05b7 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 16 Dec 2022 10:18:58 -0500 Subject: [PATCH 173/202] Feat: Added Digital Outputs for Versiports --- .../Bridges/JoinMaps/IDigitalInputJoinMap.cs | 14 +- .../Bridges/JoinMaps/IDigitalOutputJoinMap.cs | 31 +++ .../Outputs/GenericVersiportOutputDevice.cs | 176 ++++++++++++++++++ .../Crestron IO/Outputs/IDigitalOutput.cs | 17 ++ .../PepperDash_Essentials_Core.csproj | 3 + 5 files changed, 234 insertions(+), 7 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalOutputJoinMap.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/IDigitalOutput.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalInputJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalInputJoinMap.cs index 085a33bd..82c09e54 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalInputJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalInputJoinMap.cs @@ -1,10 +1,10 @@ using System; -namespace PepperDash.Essentials.Core.Bridges -{ - public class IDigitalInputJoinMap : JoinMapBaseAdvanced - { - +namespace PepperDash.Essentials.Core.Bridges +{ + public class IDigitalInputJoinMap : JoinMapBaseAdvanced + { + [JoinName("InputState")] public JoinDataComplete InputState = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, new JoinMetadata { Description = "Room Email Url", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); @@ -26,6 +26,6 @@ namespace PepperDash.Essentials.Core.Bridges protected IDigitalInputJoinMap(uint joinStart, Type type) : base(joinStart, type) { - } - } + } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalOutputJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalOutputJoinMap.cs new file mode 100644 index 00000000..cbe62398 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalOutputJoinMap.cs @@ -0,0 +1,31 @@ +using System; + +namespace PepperDash.Essentials.Core.Bridges +{ + public class IDigitalOutputJoinMap : JoinMapBaseAdvanced + { + + [JoinName("OutputState")] + public JoinDataComplete OutputState = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Get / Set state of Digital Input", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public IDigitalOutputJoinMap(uint joinStart) + : this(joinStart, typeof(IDigitalOutputJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected IDigitalOutputJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs new file mode 100644 index 00000000..197a5b19 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; + +using PepperDash.Core; +using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Core.Bridges; + + +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Core.CrestronIO +{ + /// + /// Represents a generic digital input deviced tied to a versiport + /// + public class GenericVersiportDigitalOutputDevice : EssentialsBridgeableDevice, IDigitalOutput + { + public Versiport OutputPort { get; private set; } + + public BoolFeedback OutputStateFeedback { get; private set; } + + Func OutputStateFeedbackFunc + { + get + { + return () => OutputPort.DigitalOut; + } + } + + public GenericVersiportDigitalOutputDevice(string key, string name, Func postActivationFunc, IOPortConfig config) : + base(key, name) + { + OutputStateFeedback = new BoolFeedback(OutputStateFeedbackFunc); + + AddPostActivationAction(() => + { + OutputPort = postActivationFunc(config); + + OutputPort.Register(); + + OutputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalOutput); + if (config.DisablePullUpResistor) + OutputPort.DisablePullUpResistor = true; + + OutputPort.VersiportChange += OutputPort_VersiportChange; + + + + Debug.Console(1, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, OutputPort.DisablePullUpResistor); + + }); + + } + + void OutputPort_VersiportChange(Versiport port, VersiportEventArgs args) + { + Debug.Console(1, this, "Versiport change: {0}", args.Event); + + if(args.Event == eVersiportEvent.DigitalOutChange) + OutputStateFeedback.FireUpdate(); + } + + /// + /// Set value of the versiport digital output + /// + /// value to set the output to + public void SetOutput(bool state) + { + OutputPort.DigitalOut = state; + } + + #region Bridge Linking + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new IDigitalOutputJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } + + try + { + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + // Link feedback for input state + OutputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.OutputState.JoinNumber]); + trilist.SetBoolSigAction(joinMap.OutputState.JoinNumber, SetOutput); + } + catch (Exception e) + { + Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key); + Debug.Console(1, this, "Error: {0}", e); + } + } + + #endregion + + + public static Versiport GetVersiportDigitalOutput(IOPortConfig dc) + { + + IIOPorts ioPortDevice; + + if (dc.PortDeviceKey.Equals("processor")) + { + if (!Global.ControlSystem.SupportsVersiport) + { + Debug.Console(0, "GetVersiportDigitalOuptut: Processor does not support Versiports"); + return null; + } + ioPortDevice = Global.ControlSystem; + } + else + { + var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts; + if (ioPortDev == null) + { + Debug.Console(0, "GetVersiportDigitalOuptut: Device {0} is not a valid device", dc.PortDeviceKey); + return null; + } + ioPortDevice = ioPortDev; + } + if (ioPortDevice == null) + { + Debug.Console(0, "GetVersiportDigitalOuptut: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey); + return null; + } + + if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts) + { + Debug.Console(0, "GetVersiportDigitalOuptut: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); + } + + return ioPortDevice.VersiPorts[dc.PortNumber]; + + } + } + + + public class GenericVersiportDigitalOutputDeviceFactory : EssentialsDeviceFactory + { + public GenericVersiportDigitalOutputDeviceFactory() + { + TypeNames = new List() { "versiportoutput" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new Generic Versiport Device"); + + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + + if (props == null) return null; + + var portDevice = new GenericVersiportDigitalOutputDevice(dc.Key, dc.Name, GenericVersiportDigitalOutputDevice.GetVersiportDigitalOutput, props); + + return portDevice; + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/IDigitalOutput.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/IDigitalOutput.cs new file mode 100644 index 00000000..b4151941 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/IDigitalOutput.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Essentials.Core.CrestronIO +{ + /// + /// Represents a device that provides digital input + /// + public interface IDigitalOutput + { + BoolFeedback OutputStateFeedback { get; } + void SetOutput(bool state); + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 351c781c..2cf2928c 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -123,6 +123,7 @@ + @@ -186,6 +187,8 @@ + + From e8f773b2e648fe35d430451f4f68afc5ea067632 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 16 Dec 2022 11:15:58 -0500 Subject: [PATCH 174/202] Fix: removed references to pullup resistors in versiport digital outputs --- .../Outputs/GenericVersiportOutputDevice.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs index 197a5b19..77037845 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs @@ -42,16 +42,17 @@ namespace PepperDash.Essentials.Core.CrestronIO OutputPort = postActivationFunc(config); OutputPort.Register(); - - OutputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalOutput); - if (config.DisablePullUpResistor) - OutputPort.DisablePullUpResistor = true; + if (!OutputPort.SupportsDigitalOutput) + { + Debug.Console(0, this, "Device does not support configuration as a Digital Output"); + return; + } OutputPort.VersiportChange += OutputPort_VersiportChange; - Debug.Console(1, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, OutputPort.DisablePullUpResistor); + Debug.Console(1, this, "Created GenericVersiportDigitalOutputDevice on port '{0}'.", config.PortNumber); }); From b0637288e9c353e0264a2ec958b884ed6e4825b5 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 21 Dec 2022 12:21:01 -0700 Subject: [PATCH 175/202] refactor: move logic for updating directory to method --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index aade5c0d..b5eba9c5 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -1382,22 +1382,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); - var directoryResults = - zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); - - if (!PhonebookSyncState.InitialSyncComplete) - { - PhonebookSyncState.InitialPhonebookFoldersReceived(); - PhonebookSyncState.PhonebookRootEntriesReceived(); - PhonebookSyncState.SetPhonebookHasFolders(true); - PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); - } - - directoryResults.ResultsFolderId = "root"; - - DirectoryRoot = directoryResults; - - CurrentDirectoryResult = directoryResults; + UpdateDirectory(); break; } @@ -2252,6 +2237,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } } + private void UpdateDirectory() + { + var directoryResults = + zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); + + if (!PhonebookSyncState.InitialSyncComplete) + { + PhonebookSyncState.InitialPhonebookFoldersReceived(); + PhonebookSyncState.PhonebookRootEntriesReceived(); + PhonebookSyncState.SetPhonebookHasFolders(true); + PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); + } + + directoryResults.ResultsFolderId = "root"; + + DirectoryRoot = directoryResults; + + CurrentDirectoryResult = directoryResults; + } + /// /// Will return true if the host is myself (this zoom room) /// From decc8ed3a52bfe2e4d0130cc74d40ffe18dad30c Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 22 Dec 2022 08:52:58 -0700 Subject: [PATCH 176/202] refactor: update queue error handling On some occasions, a ThreadAbortException was being caught on shutdown and causing exceptions to be printed needlessly. Messaging has also been updated to remove personal pronouns. --- .../Queues/GenericQueue.cs | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs index 9080435e..d4fe1af3 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs @@ -1,5 +1,6 @@ using System; using Crestron.SimplSharp; +using Crestron.SimplSharp.Reflection; using Crestron.SimplSharpPro.CrestronThread; using PepperDash.Core; @@ -187,9 +188,20 @@ namespace PepperDash.Essentials.Core.Queues if (_delayEnabled) Thread.Sleep(_delayTime); } + catch (System.Threading.ThreadAbortException) + { + //swallowing this exception, as it should only happen on shut down + } catch (Exception ex) { - Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Caught an exception in the Queue {0}\r{1}\r{2}", ex.Message, ex.InnerException, ex.StackTrace); + Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Caught an exception in the Queue: {1}:{0}", ex.Message, ex); + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Stack Trace: {0}", ex.StackTrace); + + if (ex.InnerException != null) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Error, "---\r\n{0}", ex.InnerException.Message); + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Stack Trace: {0}", ex.InnerException.StackTrace); + } } } else _waitHandle.Wait(); @@ -202,7 +214,7 @@ namespace PepperDash.Essentials.Core.Queues { if (Disposed) { - Debug.Console(1, this, "I've been disposed so you can't enqueue any messages. Are you trying to dispatch a message while the program is stopping?"); + Debug.Console(1, this, "Queue has been disposed. Enqueuing messages not allowed while program is stopping."); return; } @@ -446,7 +458,14 @@ namespace PepperDash_Essentials_Core.Queues } catch (Exception ex) { - Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Caught an exception in the Queue {0}\r{1}\r{2}", ex.Message, ex.InnerException, ex.StackTrace); + Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Caught an exception in the Queue {0}", ex.Message); + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Stack Trace: {0}", ex.StackTrace); + + if (ex.InnerException != null) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Caught an exception in the Queue {0}", ex.InnerException.Message); + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Stack Trace: {0}", ex.InnerException.StackTrace); + } } } else _waitHandle.Wait(); From d03581fea86aef5fc59fc338ffd67d42bc0bba4b Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 22 Dec 2022 08:54:24 -0700 Subject: [PATCH 177/202] fix: change contact message handling On some occasions when the Zoom Room restarted and Essentials did not, the directory could be requested while the Zoom Room had no contacts yet, as it hadn't received them from Zoom Cloud. This caused the directory to be empty, even though there may be valid contacts. Now, Essentials uses the Added Contact and Updated Contact methods to fire the directory changed event, allowing for directory updates to be propogated as necessary. --- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 71 ++++++++++++------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index b5eba9c5..1a70b2af 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -59,6 +59,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private CameraBase _selectedCamera; private string _lastDialedMeetingNumber; + private CTimer contactsDebounceTimer; + private readonly ZoomRoomPropertiesConfig _props; @@ -1511,36 +1513,37 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { case "phonebook": { + zStatus.Contact contact = new zStatus.Contact(); + if (responseObj["Updated Contact"] != null) - { - var updatedContact = - JsonConvert.DeserializeObject( - responseObj["Updated Contact"].ToString()); - - var existingContact = - Status.Phonebook.Contacts.FirstOrDefault(c => c.Jid.Equals(updatedContact.Jid)); - - if (existingContact != null) - { - // Update existing contact - JsonConvert.PopulateObject(responseObj["Updated Contact"].ToString(), - existingContact); - } + { + contact = responseObj["Updated Contact"].ToObject(); } else if (responseObj["Added Contact"] != null) { - var jToken = responseObj["Updated Contact"]; - if (jToken != null) - { - var newContact = - JsonConvert.DeserializeObject( - jToken.ToString()); - - // Add a new contact - Status.Phonebook.Contacts.Add(newContact); - } + contact = responseObj["Added Contact"].ToObject(); } + var existingContactIndex = Status.Phonebook.Contacts.FindIndex(c => c.Jid.Equals(contact.Jid)); + + if (existingContactIndex > 0) + { + Status.Phonebook.Contacts[existingContactIndex] = contact; + } + else + { + Status.Phonebook.Contacts.Add(contact); + } + + if(contactsDebounceTimer == null) + { + contactsDebounceTimer = new CTimer(o => UpdateDirectory(), 2000); + } + else + { + contactsDebounceTimer.Reset(); + } + break; } case "bookingslistresult": @@ -2239,8 +2242,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void UpdateDirectory() { - var directoryResults = - zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); + Debug.Console(2, this, "Updating directory"); + var directoryResults = zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); if (!PhonebookSyncState.InitialSyncComplete) { @@ -2255,6 +2258,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom DirectoryRoot = directoryResults; CurrentDirectoryResult = directoryResults; + + // + if (contactsDebounceTimer != null) + { + ClearContactDebounceTimer(); + } + } + + private void ClearContactDebounceTimer() + { + Debug.Console(2, this, "Clearing Timer"); + if (!contactsDebounceTimer.Disposed && contactsDebounceTimer != null) + { + contactsDebounceTimer.Dispose(); + contactsDebounceTimer = null; + } } /// From c14e5fe449c769fa6c0fcd00333ee67d2b422884 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 11 Jan 2023 13:57:25 -0600 Subject: [PATCH 178/202] fix: issue registering versiport digital outputs --- .../Bridges/JoinMaps/IAnalogInputJoinMap.cs | 34 + .../Bridges/JoinMaps/IDigitalInputJoinMap.cs | 2 +- .../Crestron IO/IOPortConfig.cs | 2 + .../GenericVersiportAnalogInputDevice.cs | 208 +++++ .../Crestron IO/Inputs/IAnalogInput.cs | 14 + .../Outputs/GenericVersiportOutputDevice.cs | 78 +- .../PepperDash_Essentials_Core.csproj | 3 + .../Routing/IRoutingInputsExtensions.cs | 834 +++++++++--------- 8 files changed, 724 insertions(+), 451 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IAnalogInputJoinMap.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportAnalogInputDevice.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/IAnalogInput.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IAnalogInputJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IAnalogInputJoinMap.cs new file mode 100644 index 00000000..eaf70f3a --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IAnalogInputJoinMap.cs @@ -0,0 +1,34 @@ +using System; + +namespace PepperDash.Essentials.Core.Bridges +{ + public class IAnalogInputJoinMap : JoinMapBaseAdvanced + { + + [JoinName("InputValue")] + public JoinDataComplete InputValue = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Input Value", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + [JoinName("MinimumChange")] + public JoinDataComplete MinimumChange = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Minimum voltage change required to reflect a change", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public IAnalogInputJoinMap(uint joinStart) + : this(joinStart, typeof(IAnalogInputJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected IAnalogInputJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalInputJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalInputJoinMap.cs index 82c09e54..83e6cdab 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalInputJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalInputJoinMap.cs @@ -7,7 +7,7 @@ namespace PepperDash.Essentials.Core.Bridges [JoinName("InputState")] public JoinDataComplete InputState = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Room Email Url", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + new JoinMetadata { Description = "Input State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); /// /// Constructor to use when instantiating this Join Map without inheriting from it diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/IOPortConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/IOPortConfig.cs index 09061ff2..5fbe10e1 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/IOPortConfig.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/IOPortConfig.cs @@ -15,5 +15,7 @@ namespace PepperDash.Essentials.Core.CrestronIO public uint PortNumber { get; set; } [JsonProperty("disablePullUpResistor")] public bool DisablePullUpResistor { get; set; } + [JsonProperty("minimumChange")] + public int MinimumChange { get; set; } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportAnalogInputDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportAnalogInputDevice.cs new file mode 100644 index 00000000..70be2f6f --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportAnalogInputDevice.cs @@ -0,0 +1,208 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; + +using PepperDash.Core; +using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Core.Bridges; + + +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Core.CrestronIO +{ + /// + /// Represents a generic digital input deviced tied to a versiport + /// + public class GenericVersiportAnalogInputDevice : EssentialsBridgeableDevice, IAnalogInput + { + public Versiport InputPort { get; private set; } + + public IntFeedback InputValueFeedback { get; private set; } + public IntFeedback InputMinimumChangeFeedback { get; private set; } + + Func InputValueFeedbackFunc + { + get + { + return () => InputPort.AnalogIn; + } + } + + Func InputMinimumChangeFeedbackFunc + { + get { return () => InputPort.AnalogMinChange; } + } + + public GenericVersiportAnalogInputDevice(string key, string name, Func postActivationFunc, IOPortConfig config) : + base(key, name) + { + InputValueFeedback = new IntFeedback(InputValueFeedbackFunc); + InputMinimumChangeFeedback = new IntFeedback(InputMinimumChangeFeedbackFunc); + + AddPostActivationAction(() => + { + InputPort = postActivationFunc(config); + + InputPort.Register(); + + InputPort.SetVersiportConfiguration(eVersiportConfiguration.AnalogInput); + InputPort.AnalogMinChange = (ushort)(config.MinimumChange > 0 ? config.MinimumChange : 655); + if (config.DisablePullUpResistor) + InputPort.DisablePullUpResistor = true; + + InputPort.VersiportChange += InputPort_VersiportChange; + + Debug.Console(1, this, "Created GenericVersiportAnalogInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor); + + }); + + } + + /// + /// Set minimum voltage change for device to update voltage changed method + /// + /// valid values range from 0 - 65535, representing the full 100% range of the processor voltage source. Check processor documentation for details + public void SetMinimumChange(ushort value) + { + InputPort.AnalogMinChange = value; + } + + void InputPort_VersiportChange(Versiport port, VersiportEventArgs args) + { + Debug.Console(1, this, "Versiport change: {0}", args.Event); + + if(args.Event == eVersiportEvent.AnalogInChange) + InputValueFeedback.FireUpdate(); + if (args.Event == eVersiportEvent.AnalogMinChangeChange) + InputMinimumChangeFeedback.FireUpdate(); + } + + + #region Bridge Linking + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new IAnalogInputJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } + + try + { + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + // Link feedback for input state + InputValueFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputValue.JoinNumber]); + InputMinimumChangeFeedback.LinkInputSig(trilist.UShortInput[joinMap.MinimumChange.JoinNumber]); + trilist.SetUShortSigAction(joinMap.MinimumChange.JoinNumber, SetMinimumChange); + + } + catch (Exception e) + { + Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key); + Debug.Console(1, this, "Error: {0}", e); + } + + trilist.OnlineStatusChange += (d, args) => + { + if (!args.DeviceOnLine) return; + InputValueFeedback.FireUpdate(); + InputMinimumChangeFeedback.FireUpdate(); + }; + + } + + void trilist_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args) + { + throw new NotImplementedException(); + } + + #endregion + + + public static Versiport GetVersiportDigitalInput(IOPortConfig dc) + { + + IIOPorts ioPortDevice; + + if (dc.PortDeviceKey.Equals("processor")) + { + if (!Global.ControlSystem.SupportsVersiport) + { + Debug.Console(0, "GetVersiportAnalogInput: Processor does not support Versiports"); + return null; + } + ioPortDevice = Global.ControlSystem; + } + else + { + var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts; + if (ioPortDev == null) + { + Debug.Console(0, "GetVersiportAnalogInput: Device {0} is not a valid device", dc.PortDeviceKey); + return null; + } + ioPortDevice = ioPortDev; + } + if (ioPortDevice == null) + { + Debug.Console(0, "GetVersiportAnalogInput: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey); + return null; + } + + if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts) + { + Debug.Console(0, "GetVersiportAnalogInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); + return null; + } + if(!ioPortDevice.VersiPorts[dc.PortNumber].SupportsAnalogInput) + { + Debug.Console(0, "GetVersiportAnalogInput: Device {0} does not support AnalogInput on port {1}", dc.PortDeviceKey, dc.PortNumber); + return null; + } + + + return ioPortDevice.VersiPorts[dc.PortNumber]; + + + } + } + + + public class GenericVersiportAbalogInputDeviceFactory : EssentialsDeviceFactory + { + public GenericVersiportAbalogInputDeviceFactory() + { + TypeNames = new List() { "versiportanaloginput" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new Generic Versiport Device"); + + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + + if (props == null) return null; + + var portDevice = new GenericVersiportAnalogInputDevice(dc.Key, dc.Name, GenericVersiportAnalogInputDevice.GetVersiportDigitalInput, props); + + return portDevice; + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/IAnalogInput.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/IAnalogInput.cs new file mode 100644 index 00000000..44af9954 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/IAnalogInput.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Core.CrestronIO +{ + public interface IAnalogInput + { + IntFeedback InputValueFeedback { get; } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs index 77037845..2d1ae9c4 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs @@ -42,18 +42,19 @@ namespace PepperDash.Essentials.Core.CrestronIO OutputPort = postActivationFunc(config); OutputPort.Register(); + + if (!OutputPort.SupportsDigitalOutput) { Debug.Console(0, this, "Device does not support configuration as a Digital Output"); return; } + OutputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalOutput); + + OutputPort.VersiportChange += OutputPort_VersiportChange; - - - Debug.Console(1, this, "Created GenericVersiportDigitalOutputDevice on port '{0}'.", config.PortNumber); - }); } @@ -72,7 +73,18 @@ namespace PepperDash.Essentials.Core.CrestronIO /// value to set the output to public void SetOutput(bool state) { - OutputPort.DigitalOut = state; + if (OutputPort.SupportsDigitalOutput) + { + Debug.Console(0, this, "Passed the Check"); + + OutputPort.DigitalOut = state; + + } + else + { + Debug.Console(0, this, "Versiport does not support Digital Output Mode"); + } + } #region Bridge Linking @@ -115,40 +127,40 @@ namespace PepperDash.Essentials.Core.CrestronIO public static Versiport GetVersiportDigitalOutput(IOPortConfig dc) { - - IIOPorts ioPortDevice; - if (dc.PortDeviceKey.Equals("processor")) - { - if (!Global.ControlSystem.SupportsVersiport) + IIOPorts ioPortDevice; + + if (dc.PortDeviceKey.Equals("processor")) { - Debug.Console(0, "GetVersiportDigitalOuptut: Processor does not support Versiports"); + if (!Global.ControlSystem.SupportsVersiport) + { + Debug.Console(0, "GetVersiportDigitalOuptut: Processor does not support Versiports"); + return null; + } + ioPortDevice = Global.ControlSystem; + } + else + { + var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts; + if (ioPortDev == null) + { + Debug.Console(0, "GetVersiportDigitalOuptut: Device {0} is not a valid device", dc.PortDeviceKey); + return null; + } + ioPortDevice = ioPortDev; + } + if (ioPortDevice == null) + { + Debug.Console(0, "GetVersiportDigitalOuptut: Device '0' is not a valid IOPorts Device", dc.PortDeviceKey); return null; } - ioPortDevice = Global.ControlSystem; - } - else - { - var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts; - if (ioPortDev == null) + + if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts) { - Debug.Console(0, "GetVersiportDigitalOuptut: Device {0} is not a valid device", dc.PortDeviceKey); - return null; + Debug.Console(0, "GetVersiportDigitalOuptut: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); } - ioPortDevice = ioPortDev; - } - if (ioPortDevice == null) - { - Debug.Console(0, "GetVersiportDigitalOuptut: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey); - return null; - } - - if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts) - { - Debug.Console(0, "GetVersiportDigitalOuptut: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); - } - - return ioPortDevice.VersiPorts[dc.PortNumber]; + var port = ioPortDevice.VersiPorts[dc.PortNumber]; + return port; } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 2cf2928c..268d4f12 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -123,6 +123,7 @@ + @@ -182,8 +183,10 @@ + + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index d371c2d6..4cd0d4ff 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -1,425 +1,425 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DM; - -using PepperDash.Core; - - -namespace PepperDash.Essentials.Core -{ - public class RouteRequest - { - public IRoutingSink Destination {get; set;} - public IRoutingOutputs Source {get; set;} - public eRoutingSignalType SignalType {get; set;} - - public void HandleCooldown(object sender, FeedbackEventArgs args) - { - var coolingDevice = sender as IWarmingCooling; - - if(args.BoolValue == false) - { - Destination.ReleaseAndMakeRoute(Source, SignalType); - - if(sender == null) return; - - coolingDevice.IsCoolingDownFeedback.OutputChange -= HandleCooldown; - } - } - } - - /// - /// Extensions added to any IRoutingInputs classes to provide discovery-based routing - /// on those destinations. - /// - public static class IRoutingInputsExtensions - { - private static Dictionary RouteRequests = new Dictionary(); - /// - /// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute - /// and then attempts a new Route and if sucessful, stores that RouteDescriptor - /// in RouteDescriptorCollection.DefaultCollection - /// - public static void ReleaseAndMakeRoute(this IRoutingSink destination, IRoutingOutputs source, eRoutingSignalType signalType) - { - var routeRequest = new RouteRequest { - Destination = destination, - Source = source, - SignalType = signalType - }; - - var coolingDevice = destination as IWarmingCooling; - - RouteRequest existingRouteRequest; - - //We already have a route request for this device, and it's a cooling device and is cooling - if (RouteRequests.TryGetValue(destination.Key, out existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) - { - coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; - - coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; - +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DM; + +using PepperDash.Core; + + +namespace PepperDash.Essentials.Core +{ + public class RouteRequest + { + public IRoutingSink Destination {get; set;} + public IRoutingOutputs Source {get; set;} + public eRoutingSignalType SignalType {get; set;} + + public void HandleCooldown(object sender, FeedbackEventArgs args) + { + var coolingDevice = sender as IWarmingCooling; + + if(args.BoolValue == false) + { + Destination.ReleaseAndMakeRoute(Source, SignalType); + + if(sender == null) return; + + coolingDevice.IsCoolingDownFeedback.OutputChange -= HandleCooldown; + } + } + } + + /// + /// Extensions added to any IRoutingInputs classes to provide discovery-based routing + /// on those destinations. + /// + public static class IRoutingInputsExtensions + { + private static Dictionary RouteRequests = new Dictionary(); + /// + /// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute + /// and then attempts a new Route and if sucessful, stores that RouteDescriptor + /// in RouteDescriptorCollection.DefaultCollection + /// + public static void ReleaseAndMakeRoute(this IRoutingSink destination, IRoutingOutputs source, eRoutingSignalType signalType) + { + var routeRequest = new RouteRequest { + Destination = destination, + Source = source, + SignalType = signalType + }; + + var coolingDevice = destination as IWarmingCooling; + + RouteRequest existingRouteRequest; + + //We already have a route request for this device, and it's a cooling device and is cooling + if (RouteRequests.TryGetValue(destination.Key, out existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) + { + coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; + + coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; + RouteRequests[destination.Key] = routeRequest; - Debug.Console(2, "******************************************************** Device: {0} is cooling down and already has a routing request stored. Storing new route request to route to source key: {1}", destination.Key, routeRequest.Source.Key); - - return; - } - - //New Request - if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) - { - coolingDevice.IsCoolingDownFeedback.OutputChange -= routeRequest.HandleCooldown; - - coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; - + 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) - { + 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(); - } - - /// - /// Will release the existing route on the destination, if it is found in - /// RouteDescriptorCollection.DefaultCollection - /// - /// - public static void ReleaseRoute(this IRoutingSink destination) - { - RouteRequest existingRequest; - - if (RouteRequests.TryGetValue(destination.Key, out existingRequest) && destination is IWarmingCooling) - { - var coolingDevice = destination as IWarmingCooling; - - coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown; - } - - RouteRequests.Remove(destination.Key); - - var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination); - if (current != null) - { - Debug.Console(1, destination, "Releasing current route: {0}", current.Source.Key); - current.ReleaseRoutes(); - } - } - - /// - /// Builds a RouteDescriptor that contains the steps necessary to make a route between devices. - /// Routes of type AudioVideo will be built as two separate routes, audio and video. If - /// a route is discovered, a new RouteDescriptor is returned. If one or both parts - /// of an audio/video route are discovered a route descriptor is returned. If no route is - /// discovered, then null is returned - /// - public static RouteDescriptor GetRouteToSource(this IRoutingSink destination, IRoutingOutputs source, eRoutingSignalType signalType) - { - var routeDescr = new RouteDescriptor(source, destination, signalType); - // if it's a single signal type, find the route - if ((signalType & (eRoutingSignalType.Audio & eRoutingSignalType.Video)) == (eRoutingSignalType.Audio & eRoutingSignalType.Video)) - { - Debug.Console(1, destination, "Attempting to build source route from {0}", source.Key); - if (!destination.GetRouteToSource(source, null, null, signalType, 0, routeDescr)) - routeDescr = null; - } - // otherwise, audioVideo needs to be handled as two steps. - else - { - Debug.Console(1, destination, "Attempting to build audio and video routes from {0}", source.Key); - var audioSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Audio, 0, routeDescr); - if (!audioSuccess) - Debug.Console(1, destination, "Cannot find audio route to {0}", source.Key); - var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, routeDescr); - if (!videoSuccess) - Debug.Console(1, destination, "Cannot find video route to {0}", source.Key); - if (!audioSuccess && !videoSuccess) - routeDescr = null; - } - - //Debug.Console(1, destination, "Route{0} discovered", routeDescr == null ? " NOT" : ""); - return routeDescr; - } - - /// - /// The recursive part of this. Will stop on each device, search its inputs for the - /// desired source and if not found, invoke this function for the each input port - /// hoping to find the source. - /// - /// - /// - /// The RoutingOutputPort whose link is being checked for a route - /// Prevents Devices from being twice-checked - /// This recursive function should not be called with AudioVideo - /// Just an informational counter - /// The RouteDescriptor being populated as the route is discovered - /// true if source is hit - static bool GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, - RoutingOutputPort outputPortToUse, List alreadyCheckedDevices, - eRoutingSignalType signalType, int cycle, RouteDescriptor routeTable) - { - cycle++; - Debug.Console(2, "GetRouteToSource: {0} {1}--> {2}", cycle, source.Key, destination.Key); - - RoutingInputPort goodInputPort = null; - var destDevInputTies = TieLineCollection.Default.Where(t => - t.DestinationPort.ParentDevice == destination && (t.Type == signalType || (t.Type & (eRoutingSignalType.Audio | eRoutingSignalType.Video)) == (eRoutingSignalType.Audio | eRoutingSignalType.Video))); - - // find a direct tie - var directTie = destDevInputTies.FirstOrDefault( - t => t.DestinationPort.ParentDevice == destination - && t.SourcePort.ParentDevice == source); - if (directTie != null) // Found a tie directly to the source - { - goodInputPort = directTie.DestinationPort; - } - else // no direct-connect. Walk back devices. - { - Debug.Console(2, destination, "is not directly connected to {0}. Walking down tie lines", source.Key); - - // No direct tie? Run back out on the inputs' attached devices... - // Only the ones that are routing devices - var attachedMidpoints = destDevInputTies.Where(t => t.SourcePort.ParentDevice is IRoutingInputsOutputs); - - //Create a list for tracking already checked devices to avoid loops, if it doesn't already exist from previous iteration - if (alreadyCheckedDevices == null) - alreadyCheckedDevices = new List(); - alreadyCheckedDevices.Add(destination as IRoutingInputsOutputs); - - foreach (var inputTieToTry in attachedMidpoints) - { - var upstreamDeviceOutputPort = inputTieToTry.SourcePort; - var upstreamRoutingDevice = upstreamDeviceOutputPort.ParentDevice as IRoutingInputsOutputs; - Debug.Console(2, destination, "Trying to find route on {0}", upstreamRoutingDevice.Key); - - // Check if this previous device has already been walked - if (alreadyCheckedDevices.Contains(upstreamRoutingDevice)) - { - Debug.Console(2, destination, "Skipping input {0} on {1}, this was already checked", upstreamRoutingDevice.Key, destination.Key); - continue; - } - // haven't seen this device yet. Do it. Pass the output port to the next - // level to enable switching on success - var upstreamRoutingSuccess = upstreamRoutingDevice.GetRouteToSource(source, upstreamDeviceOutputPort, - alreadyCheckedDevices, signalType, cycle, routeTable); - if (upstreamRoutingSuccess) - { - Debug.Console(2, destination, "Upstream device route found"); - goodInputPort = inputTieToTry.DestinationPort; - break; // Stop looping the inputs in this cycle - } - } - } - - // we have a route on corresponding inputPort. *** Do the route *** - if (goodInputPort != null) - { - //Debug.Console(2, destination, "adding RouteDescriptor"); - if (outputPortToUse == null) - { - // it's a sink device - routeTable.Routes.Add(new RouteSwitchDescriptor(goodInputPort)); - } - else if (destination is IRouting) - { - routeTable.Routes.Add(new RouteSwitchDescriptor (outputPortToUse, goodInputPort)); - } - else // device is merely IRoutingInputOutputs - Debug.Console(2, destination, " No routing. Passthrough device"); - //Debug.Console(2, destination, "Exiting cycle {0}", cycle); - return true; - } - - Debug.Console(2, destination, "No route found to {0}", source.Key); - return false; - } - } - - - - - - // MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE - - - /// - /// A collection of RouteDescriptors - typically the static DefaultCollection is used - /// - public class RouteDescriptorCollection - { - public static RouteDescriptorCollection DefaultCollection - { - get - { - if (_DefaultCollection == null) - _DefaultCollection = new RouteDescriptorCollection(); - return _DefaultCollection; - } - } - static RouteDescriptorCollection _DefaultCollection; - - List RouteDescriptors = new List(); - - /// - /// Adds a RouteDescriptor to the list. If an existing RouteDescriptor for the - /// destination exists already, it will not be added - in order to preserve - /// proper route releasing. - /// - /// - public void AddRouteDescriptor(RouteDescriptor descriptor) - { - if (RouteDescriptors.Any(t => t.Destination == descriptor.Destination)) - { - Debug.Console(1, descriptor.Destination, - "Route to [{0}] already exists in global routes table", descriptor.Source.Key); - return; - } - RouteDescriptors.Add(descriptor); - } - - /// - /// Gets the RouteDescriptor for a destination - /// - /// null if no RouteDescriptor for a destination exists - public RouteDescriptor GetRouteDescriptorForDestination(IRoutingInputs destination) - { - return RouteDescriptors.FirstOrDefault(rd => rd.Destination == destination); - } - - /// - /// Returns the RouteDescriptor for a given destination AND removes it from collection. - /// Returns null if no route with the provided destination exists. - /// - public RouteDescriptor RemoveRouteDescriptor(IRoutingInputs destination) - { - var descr = GetRouteDescriptorForDestination(destination); - if (descr != null) - RouteDescriptors.Remove(descr); - return descr; - } - } - - /// - /// Represents an collection of individual route steps between Source and Destination - /// - public class RouteDescriptor - { - public IRoutingInputs Destination { get; private set; } - public IRoutingOutputs Source { get; private set; } - public eRoutingSignalType SignalType { get; private set; } - public List Routes { get; private set; } - - - public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) - { - Destination = destination; - Source = source; - SignalType = signalType; - Routes = new List(); - } - - /// - /// Executes all routes described in this collection. Typically called via - /// extension method IRoutingInputs.ReleaseAndMakeRoute() - /// - public void ExecuteRoutes() - { - foreach (var route in Routes) - { - Debug.Console(2, "ExecuteRoutes: {0}", route.ToString()); - if (route.SwitchingDevice is IRoutingSink) - { - var device = route.SwitchingDevice as IRoutingSinkWithSwitching; - if (device == null) - continue; - - device.ExecuteSwitch(route.InputPort.Selector); - } - else if (route.SwitchingDevice is IRouting) - { - (route.SwitchingDevice as IRouting).ExecuteSwitch(route.InputPort.Selector, route.OutputPort.Selector, SignalType); - route.OutputPort.InUseTracker.AddUser(Destination, "destination-" + SignalType); - Debug.Console(2, "Output port {0} routing. Count={1}", route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); - } - } - } - - /// - /// Releases all routes in this collection. Typically called via - /// extension method IRoutingInputs.ReleaseAndMakeRoute() - /// - public void ReleaseRoutes() - { - foreach (var route in Routes) - { - if (route.SwitchingDevice is IRouting) - { - // Pull the route from the port. Whatever is watching the output's in use tracker is - // responsible for responding appropriately. - route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType); - Debug.Console(2, "Port {0} releasing. Count={1}", route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); - } - } - } - - public override string ToString() - { - var routesText = Routes.Select(r => r.ToString()).ToArray(); - return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText)); - } - } - - /// - /// Represents an individual link for a route - /// - public class RouteSwitchDescriptor - { - public IRoutingInputs SwitchingDevice { get { return InputPort.ParentDevice; } } - public RoutingOutputPort OutputPort { get; set; } - public RoutingInputPort InputPort { get; set; } - - public RouteSwitchDescriptor(RoutingInputPort inputPort) - { - InputPort = inputPort; - } - - public RouteSwitchDescriptor(RoutingOutputPort outputPort, RoutingInputPort inputPort) - { - InputPort = inputPort; - OutputPort = outputPort; - } - - public override string ToString() - { - if(SwitchingDevice is IRouting) - return string.Format("{0} switches output '{1}' to input '{2}'", SwitchingDevice.Key, OutputPort.Selector, InputPort.Selector); - else - return string.Format("{0} switches to input '{1}'", SwitchingDevice.Key, InputPort.Selector); - - } - } + } + + 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(); + } + + /// + /// Will release the existing route on the destination, if it is found in + /// RouteDescriptorCollection.DefaultCollection + /// + /// + public static void ReleaseRoute(this IRoutingSink destination) + { + RouteRequest existingRequest; + + if (RouteRequests.TryGetValue(destination.Key, out existingRequest) && destination is IWarmingCooling) + { + var coolingDevice = destination as IWarmingCooling; + + coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown; + } + + RouteRequests.Remove(destination.Key); + + var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination); + if (current != null) + { + Debug.Console(1, destination, "Releasing current route: {0}", current.Source.Key); + current.ReleaseRoutes(); + } + } + + /// + /// Builds a RouteDescriptor that contains the steps necessary to make a route between devices. + /// Routes of type AudioVideo will be built as two separate routes, audio and video. If + /// a route is discovered, a new RouteDescriptor is returned. If one or both parts + /// of an audio/video route are discovered a route descriptor is returned. If no route is + /// discovered, then null is returned + /// + public static RouteDescriptor GetRouteToSource(this IRoutingSink destination, IRoutingOutputs source, eRoutingSignalType signalType) + { + var routeDescr = new RouteDescriptor(source, destination, signalType); + // if it's a single signal type, find the route + if ((signalType & (eRoutingSignalType.Audio & eRoutingSignalType.Video)) == (eRoutingSignalType.Audio & eRoutingSignalType.Video)) + { + Debug.Console(1, destination, "Attempting to build source route from {0}", source.Key); + if (!destination.GetRouteToSource(source, null, null, signalType, 0, routeDescr)) + routeDescr = null; + } + // otherwise, audioVideo needs to be handled as two steps. + else + { + Debug.Console(1, destination, "Attempting to build audio and video routes from {0}", source.Key); + var audioSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Audio, 0, routeDescr); + if (!audioSuccess) + Debug.Console(1, destination, "Cannot find audio route to {0}", source.Key); + var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, routeDescr); + if (!videoSuccess) + Debug.Console(1, destination, "Cannot find video route to {0}", source.Key); + if (!audioSuccess && !videoSuccess) + routeDescr = null; + } + + //Debug.Console(1, destination, "Route{0} discovered", routeDescr == null ? " NOT" : ""); + return routeDescr; + } + + /// + /// The recursive part of this. Will stop on each device, search its inputs for the + /// desired source and if not found, invoke this function for the each input port + /// hoping to find the source. + /// + /// + /// + /// The RoutingOutputPort whose link is being checked for a route + /// Prevents Devices from being twice-checked + /// This recursive function should not be called with AudioVideo + /// Just an informational counter + /// The RouteDescriptor being populated as the route is discovered + /// true if source is hit + static bool GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, + RoutingOutputPort outputPortToUse, List alreadyCheckedDevices, + eRoutingSignalType signalType, int cycle, RouteDescriptor routeTable) + { + cycle++; + Debug.Console(2, "GetRouteToSource: {0} {1}--> {2}", cycle, source.Key, destination.Key); + + RoutingInputPort goodInputPort = null; + var destDevInputTies = TieLineCollection.Default.Where(t => + t.DestinationPort.ParentDevice == destination && (t.Type == signalType || (t.Type & (eRoutingSignalType.Audio | eRoutingSignalType.Video)) == (eRoutingSignalType.Audio | eRoutingSignalType.Video))); + + // find a direct tie + var directTie = destDevInputTies.FirstOrDefault( + t => t.DestinationPort.ParentDevice == destination + && t.SourcePort.ParentDevice == source); + if (directTie != null) // Found a tie directly to the source + { + goodInputPort = directTie.DestinationPort; + } + else // no direct-connect. Walk back devices. + { + Debug.Console(2, destination, "is not directly connected to {0}. Walking down tie lines", source.Key); + + // No direct tie? Run back out on the inputs' attached devices... + // Only the ones that are routing devices + var attachedMidpoints = destDevInputTies.Where(t => t.SourcePort.ParentDevice is IRoutingInputsOutputs); + + //Create a list for tracking already checked devices to avoid loops, if it doesn't already exist from previous iteration + if (alreadyCheckedDevices == null) + alreadyCheckedDevices = new List(); + alreadyCheckedDevices.Add(destination as IRoutingInputsOutputs); + + foreach (var inputTieToTry in attachedMidpoints) + { + var upstreamDeviceOutputPort = inputTieToTry.SourcePort; + var upstreamRoutingDevice = upstreamDeviceOutputPort.ParentDevice as IRoutingInputsOutputs; + Debug.Console(2, destination, "Trying to find route on {0}", upstreamRoutingDevice.Key); + + // Check if this previous device has already been walked + if (alreadyCheckedDevices.Contains(upstreamRoutingDevice)) + { + Debug.Console(2, destination, "Skipping input {0} on {1}, this was already checked", upstreamRoutingDevice.Key, destination.Key); + continue; + } + // haven't seen this device yet. Do it. Pass the output port to the next + // level to enable switching on success + var upstreamRoutingSuccess = upstreamRoutingDevice.GetRouteToSource(source, upstreamDeviceOutputPort, + alreadyCheckedDevices, signalType, cycle, routeTable); + if (upstreamRoutingSuccess) + { + Debug.Console(2, destination, "Upstream device route found"); + goodInputPort = inputTieToTry.DestinationPort; + break; // Stop looping the inputs in this cycle + } + } + } + + // we have a route on corresponding inputPort. *** Do the route *** + if (goodInputPort != null) + { + //Debug.Console(2, destination, "adding RouteDescriptor"); + if (outputPortToUse == null) + { + // it's a sink device + routeTable.Routes.Add(new RouteSwitchDescriptor(goodInputPort)); + } + else if (destination is IRouting) + { + routeTable.Routes.Add(new RouteSwitchDescriptor (outputPortToUse, goodInputPort)); + } + else // device is merely IRoutingInputOutputs + Debug.Console(2, destination, " No routing. Passthrough device"); + //Debug.Console(2, destination, "Exiting cycle {0}", cycle); + return true; + } + + Debug.Console(2, destination, "No route found to {0}", source.Key); + return false; + } + } + + + + + + // MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE MOVE + + + /// + /// A collection of RouteDescriptors - typically the static DefaultCollection is used + /// + public class RouteDescriptorCollection + { + public static RouteDescriptorCollection DefaultCollection + { + get + { + if (_DefaultCollection == null) + _DefaultCollection = new RouteDescriptorCollection(); + return _DefaultCollection; + } + } + static RouteDescriptorCollection _DefaultCollection; + + List RouteDescriptors = new List(); + + /// + /// Adds a RouteDescriptor to the list. If an existing RouteDescriptor for the + /// destination exists already, it will not be added - in order to preserve + /// proper route releasing. + /// + /// + public void AddRouteDescriptor(RouteDescriptor descriptor) + { + if (RouteDescriptors.Any(t => t.Destination == descriptor.Destination)) + { + Debug.Console(1, descriptor.Destination, + "Route to [{0}] already exists in global routes table", descriptor.Source.Key); + return; + } + RouteDescriptors.Add(descriptor); + } + + /// + /// Gets the RouteDescriptor for a destination + /// + /// null if no RouteDescriptor for a destination exists + public RouteDescriptor GetRouteDescriptorForDestination(IRoutingInputs destination) + { + return RouteDescriptors.FirstOrDefault(rd => rd.Destination == destination); + } + + /// + /// Returns the RouteDescriptor for a given destination AND removes it from collection. + /// Returns null if no route with the provided destination exists. + /// + public RouteDescriptor RemoveRouteDescriptor(IRoutingInputs destination) + { + var descr = GetRouteDescriptorForDestination(destination); + if (descr != null) + RouteDescriptors.Remove(descr); + return descr; + } + } + + /// + /// Represents an collection of individual route steps between Source and Destination + /// + public class RouteDescriptor + { + public IRoutingInputs Destination { get; private set; } + public IRoutingOutputs Source { get; private set; } + public eRoutingSignalType SignalType { get; private set; } + public List Routes { get; private set; } + + + public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) + { + Destination = destination; + Source = source; + SignalType = signalType; + Routes = new List(); + } + + /// + /// Executes all routes described in this collection. Typically called via + /// extension method IRoutingInputs.ReleaseAndMakeRoute() + /// + public void ExecuteRoutes() + { + foreach (var route in Routes) + { + Debug.Console(2, "ExecuteRoutes: {0}", route.ToString()); + if (route.SwitchingDevice is IRoutingSink) + { + var device = route.SwitchingDevice as IRoutingSinkWithSwitching; + if (device == null) + continue; + + device.ExecuteSwitch(route.InputPort.Selector); + } + else if (route.SwitchingDevice is IRouting) + { + (route.SwitchingDevice as IRouting).ExecuteSwitch(route.InputPort.Selector, route.OutputPort.Selector, SignalType); + route.OutputPort.InUseTracker.AddUser(Destination, "destination-" + SignalType); + Debug.Console(2, "Output port {0} routing. Count={1}", route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); + } + } + } + + /// + /// Releases all routes in this collection. Typically called via + /// extension method IRoutingInputs.ReleaseAndMakeRoute() + /// + public void ReleaseRoutes() + { + foreach (var route in Routes) + { + if (route.SwitchingDevice is IRouting) + { + // Pull the route from the port. Whatever is watching the output's in use tracker is + // responsible for responding appropriately. + route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType); + Debug.Console(2, "Port {0} releasing. Count={1}", route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); + } + } + } + + public override string ToString() + { + var routesText = Routes.Select(r => r.ToString()).ToArray(); + return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText)); + } + } + + /// + /// Represents an individual link for a route + /// + public class RouteSwitchDescriptor + { + public IRoutingInputs SwitchingDevice { get { return InputPort.ParentDevice; } } + public RoutingOutputPort OutputPort { get; set; } + public RoutingInputPort InputPort { get; set; } + + public RouteSwitchDescriptor(RoutingInputPort inputPort) + { + InputPort = inputPort; + } + + public RouteSwitchDescriptor(RoutingOutputPort outputPort, RoutingInputPort inputPort) + { + InputPort = inputPort; + OutputPort = outputPort; + } + + public override string ToString() + { + if(SwitchingDevice is IRouting) + return string.Format("{0} switches output '{1}' to input '{2}'", SwitchingDevice.Key, OutputPort.Selector, InputPort.Selector); + else + return string.Format("{0} switches to input '{1}'", SwitchingDevice.Key, InputPort.Selector); + + } + } } \ No newline at end of file From 6414631debcc762e26ecd59e2dbd74c8de160e5a Mon Sep 17 00:00:00 2001 From: jdevito Date: Tue, 17 Jan 2023 09:49:16 -0600 Subject: [PATCH 179/202] feat: added crestron web server (cws) to Essentials_Core --- .../CrestronWebServerBase.cs | 197 ++++++++++++++++++ .../CrestronWebServerFactory.cs | 20 ++ .../RequestHandlerUnknown.cs | 19 ++ 3 files changed, 236 insertions(+) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerBase.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerFactory.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/RequestHandlerUnknown.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerBase.cs new file mode 100644 index 00000000..d9649a7d --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerBase.cs @@ -0,0 +1,197 @@ +using System; +using Crestron.SimplSharp; +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core +{ + public class CrestronWebServerBase : EssentialsDevice, IDisposable + { + private HttpCwsServer _server; + private readonly CCriticalSection _serverLock = new CCriticalSection(); + + /// + /// CWS base path + /// + public string BasePath { get; private set; } + + /// + /// Constructor + /// + /// + /// + /// + public CrestronWebServerBase(string key, string name, string basePath) + : base(key, name) + { + Key = key; + + BasePath = string.IsNullOrEmpty(basePath) ? "/api" : basePath; + + CrestronEnvironment.ProgramStatusEventHandler += programEvent => + { + if (programEvent != eProgramStatusEventType.Stopping) + return; + + Dispose(true); + }; + } + + /// + /// Initializes the CWS class + /// + public override void Initialize() + { + ServerStart(); + base.Initialize(); + } + + /// + /// Starts the CWS server + /// + public void ServerStart() + { + try + { + _serverLock.Enter(); + + if (_server != null) + { + Debug.Console(1, this, "Server is already running"); + return; + } + + Debug.Console(1, this, "Starting server"); + + _server = new HttpCwsServer(BasePath) + { + HttpRequestHandler = new RequestHandlerUnknown() + }; + + // TODO [ ] Add server paths + } + catch (Exception ex) + { + Debug.Console(1, this, "ServerStart Exception Message: {0}", ex.Message); + Debug.Console(2, this, "ServerStart Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) + Debug.Console(2, this, "ServerStart Exception InnerException: {0}", ex.InnerException); + } + finally + { + _serverLock.Leave(); + } + } + + /// + /// Stops the CWS server + /// + public void ServerStop() + { + try + { + _serverLock.Enter(); + if (_server == null) + { + Debug.Console(1, this, "Server is already stopped"); + return; + } + + _server.Unregister(); + _server.Dispose(); + _server = null; + } + catch (Exception ex) + { + Debug.Console(1, this, "ServerStop Exception Message: {0}", ex.Message); + Debug.Console(2, this, "ServerStop Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) + Debug.Console(2, this, "ServerStop Exception InnerException: {0}", ex.InnerException); + } + finally + { + _serverLock.Leave(); + } + } + + /// + /// Received request handler + /// + /// + /// + public void ReceivedRequestEventHandler(object sender, HttpCwsRequestEventArgs args) + { + try + { + // TODO [ ] Add logic for received requests + Debug.Console(1, this, @"RecieveRequestEventHandler +Method: {0} +Path: {1} +PathInfo: {2} +PhysicalPath: {3} +ContentType: {4} +RawUrl: {5} +Url: {6} +UserAgent: {7} +UserHostAddress: {8} +UserHostName: {9}", + args.Context.Request.HttpMethod, + args.Context.Request.Path, + args.Context.Request.PathInfo, + args.Context.Request.PhysicalPath, + args.Context.Request.ContentType, + args.Context.Request.RawUrl, + args.Context.Request.Url, + args.Context.Request.UserAgent, + args.Context.Request.UserHostAddress, + args.Context.Request.UserHostName); + + } + catch (Exception ex) + { + Debug.Console(1, this, "ReceivedRequestEventHandler Exception Message: {0}", ex.Message); + Debug.Console(2, this, "ReceivedRequestEventHandler Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) + Debug.Console(2, this, "ReceivedRequestEventHandler Exception InnerException: {0}", ex.InnerException); + } + } + + #region Dispose + + /// + /// Tracks if the CWS is disposed + /// + public bool Disposed { get; private set; } + + /// + /// Disposes of the CWS + /// + public void Dispose() + { + Dispose(true); + CrestronEnvironment.GC.SuppressFinalize(this); + } + + protected void Dispose(bool disposing) + { + if (Disposed) + { + Debug.Console(1, this, "Server has already been disposed"); + return; + } + + if (!disposing) return; + + if (_server != null) ServerStop(); + + Disposed = _server == null; + } + + ~CrestronWebServerBase() + { + Dispose(true); + } + + #endregion + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerFactory.cs new file mode 100644 index 00000000..ab442ecb --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerFactory.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using PepperDash.Core; +using PepperDash.Essentials.Core.Config; + +namespace PepperDash.Essentials.Core +{ + public class CrestronWebServerFactory : EssentialsDeviceFactory + { + public CrestronWebServerFactory() + { + TypeNames = new List { "crestroncws", "cws" }; + } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new Crestron CWS Device"); + + return new CrestronWebServerBase(dc.Key, dc.Name, ""); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/RequestHandlerUnknown.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/RequestHandlerUnknown.cs new file mode 100644 index 00000000..71cf383a --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/RequestHandlerUnknown.cs @@ -0,0 +1,19 @@ +using Crestron.SimplSharp.WebScripting; + +namespace PepperDash.Essentials.Core +{ + /// + /// Crestron CWS unknown request handler + /// + public class RequestHandlerUnknown : IHttpCwsHandler + { + + public void ProcessRequest(HttpCwsContext context) + { + // TODO [ ] Modify unknown request handler + context.Response.StatusCode = 418; + context.Response.ContentType = "application/json"; + context.Response.Write(string.Format("{0} {1}", context.Request.HttpMethod, context.Request.RawUrl), true); + } + } +} \ No newline at end of file From b52bee5714385232bff2e06ca33fa647fc344ed9 Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 18 Jan 2023 15:26:24 -0600 Subject: [PATCH 180/202] refactor: Changed CWS references to WebApi, re-organized Web folder; added generic request handlers to align with API, handlers need to be completed --- .../CrestronWebServerBase.cs | 197 ------------------ .../CrestronWebServerFactory.cs | 20 -- .../RequestHandlerUnknown.cs | 19 -- .../PepperDash_Essentials_Core.csproj | 17 ++ ...perDash_Essentials_Core.csproj.DotSettings | 3 + .../Web/EssemtialsWebApi.cs | 160 ++++++++++++++ .../Web/EssentialsWebApiFactory.cs | 25 +++ .../Web/EssentialsWebApiPropertiesConfig.cs | 10 + .../RequestHandlers/AppDebugRequestHandler.cs | 111 ++++++++++ .../RequestHandlers/DevJsonRequestHandler.cs | 111 ++++++++++ .../RequestHandlers/DevListRequestHandler.cs | 111 ++++++++++ .../RequestHandlers/DevPropsRequestHandler.cs | 111 ++++++++++ .../DisableAllStreamDebugRequestHandler.cs | 111 ++++++++++ .../GetJoinMapRequestHandler.cs | 111 ++++++++++ .../RequestHandlers/GetTypesRequestHandler.cs | 111 ++++++++++ .../ReportVersionsRequestHandler.cs | 111 ++++++++++ .../SetDeviceStreamDebugRequestHandler.cs | 111 ++++++++++ .../ShowConfigRequestHandler.cs | 111 ++++++++++ packages.config | 2 +- 19 files changed, 1326 insertions(+), 237 deletions(-) delete mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerBase.cs delete mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerFactory.cs delete mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/RequestHandlerUnknown.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj.DotSettings create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiFactory.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiPropertiesConfig.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerBase.cs deleted file mode 100644 index d9649a7d..00000000 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerBase.cs +++ /dev/null @@ -1,197 +0,0 @@ -using System; -using Crestron.SimplSharp; -using Crestron.SimplSharp.WebScripting; -using PepperDash.Core; - -namespace PepperDash.Essentials.Core -{ - public class CrestronWebServerBase : EssentialsDevice, IDisposable - { - private HttpCwsServer _server; - private readonly CCriticalSection _serverLock = new CCriticalSection(); - - /// - /// CWS base path - /// - public string BasePath { get; private set; } - - /// - /// Constructor - /// - /// - /// - /// - public CrestronWebServerBase(string key, string name, string basePath) - : base(key, name) - { - Key = key; - - BasePath = string.IsNullOrEmpty(basePath) ? "/api" : basePath; - - CrestronEnvironment.ProgramStatusEventHandler += programEvent => - { - if (programEvent != eProgramStatusEventType.Stopping) - return; - - Dispose(true); - }; - } - - /// - /// Initializes the CWS class - /// - public override void Initialize() - { - ServerStart(); - base.Initialize(); - } - - /// - /// Starts the CWS server - /// - public void ServerStart() - { - try - { - _serverLock.Enter(); - - if (_server != null) - { - Debug.Console(1, this, "Server is already running"); - return; - } - - Debug.Console(1, this, "Starting server"); - - _server = new HttpCwsServer(BasePath) - { - HttpRequestHandler = new RequestHandlerUnknown() - }; - - // TODO [ ] Add server paths - } - catch (Exception ex) - { - Debug.Console(1, this, "ServerStart Exception Message: {0}", ex.Message); - Debug.Console(2, this, "ServerStart Exception StackTrace: {0}", ex.StackTrace); - if (ex.InnerException != null) - Debug.Console(2, this, "ServerStart Exception InnerException: {0}", ex.InnerException); - } - finally - { - _serverLock.Leave(); - } - } - - /// - /// Stops the CWS server - /// - public void ServerStop() - { - try - { - _serverLock.Enter(); - if (_server == null) - { - Debug.Console(1, this, "Server is already stopped"); - return; - } - - _server.Unregister(); - _server.Dispose(); - _server = null; - } - catch (Exception ex) - { - Debug.Console(1, this, "ServerStop Exception Message: {0}", ex.Message); - Debug.Console(2, this, "ServerStop Exception StackTrace: {0}", ex.StackTrace); - if (ex.InnerException != null) - Debug.Console(2, this, "ServerStop Exception InnerException: {0}", ex.InnerException); - } - finally - { - _serverLock.Leave(); - } - } - - /// - /// Received request handler - /// - /// - /// - public void ReceivedRequestEventHandler(object sender, HttpCwsRequestEventArgs args) - { - try - { - // TODO [ ] Add logic for received requests - Debug.Console(1, this, @"RecieveRequestEventHandler -Method: {0} -Path: {1} -PathInfo: {2} -PhysicalPath: {3} -ContentType: {4} -RawUrl: {5} -Url: {6} -UserAgent: {7} -UserHostAddress: {8} -UserHostName: {9}", - args.Context.Request.HttpMethod, - args.Context.Request.Path, - args.Context.Request.PathInfo, - args.Context.Request.PhysicalPath, - args.Context.Request.ContentType, - args.Context.Request.RawUrl, - args.Context.Request.Url, - args.Context.Request.UserAgent, - args.Context.Request.UserHostAddress, - args.Context.Request.UserHostName); - - } - catch (Exception ex) - { - Debug.Console(1, this, "ReceivedRequestEventHandler Exception Message: {0}", ex.Message); - Debug.Console(2, this, "ReceivedRequestEventHandler Exception StackTrace: {0}", ex.StackTrace); - if (ex.InnerException != null) - Debug.Console(2, this, "ReceivedRequestEventHandler Exception InnerException: {0}", ex.InnerException); - } - } - - #region Dispose - - /// - /// Tracks if the CWS is disposed - /// - public bool Disposed { get; private set; } - - /// - /// Disposes of the CWS - /// - public void Dispose() - { - Dispose(true); - CrestronEnvironment.GC.SuppressFinalize(this); - } - - protected void Dispose(bool disposing) - { - if (Disposed) - { - Debug.Console(1, this, "Server has already been disposed"); - return; - } - - if (!disposing) return; - - if (_server != null) ServerStop(); - - Disposed = _server == null; - } - - ~CrestronWebServerBase() - { - Dispose(true); - } - - #endregion - } -} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerFactory.cs deleted file mode 100644 index ab442ecb..00000000 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/CrestronWebServerFactory.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Collections.Generic; -using PepperDash.Core; -using PepperDash.Essentials.Core.Config; - -namespace PepperDash.Essentials.Core -{ - public class CrestronWebServerFactory : EssentialsDeviceFactory - { - public CrestronWebServerFactory() - { - TypeNames = new List { "crestroncws", "cws" }; - } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.Console(1, "Factory Attempting to create new Crestron CWS Device"); - - return new CrestronWebServerBase(dc.Key, dc.Name, ""); - } - } -} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/RequestHandlerUnknown.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/RequestHandlerUnknown.cs deleted file mode 100644 index 71cf383a..00000000 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron Web Server/RequestHandlerUnknown.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Crestron.SimplSharp.WebScripting; - -namespace PepperDash.Essentials.Core -{ - /// - /// Crestron CWS unknown request handler - /// - public class RequestHandlerUnknown : IHttpCwsHandler - { - - public void ProcessRequest(HttpCwsContext context) - { - // TODO [ ] Modify unknown request handler - context.Response.StatusCode = 418; - context.Response.ContentType = "application/json"; - context.Response.Write(string.Format("{0} {1}", context.Request.HttpMethod, context.Request.RawUrl), true); - } - } -} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 2cf2928c..fb861df6 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -92,6 +92,10 @@ ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll False + + False + ..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCWSHelperInterface.dll + False ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll @@ -193,6 +197,19 @@ + + + + + + + + + + + + + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj.DotSettings b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj.DotSettings new file mode 100644 index 00000000..cb991a69 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj.DotSettings @@ -0,0 +1,3 @@ + + True + False \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs new file mode 100644 index 00000000..9e6fe64c --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs @@ -0,0 +1,160 @@ +using System.Collections.Generic; +using Crestron.SimplSharp; +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; +using PepperDash.Essentials.Core.Web.RequestHandlers; + +namespace PepperDash.Essentials.Core.Web +{ + public class EssemtialsWebApi : EssentialsDevice + { + private readonly GenericCwsBase _server; + + private const string DefaultBasePath = "/api"; + + private const int DebugTrace = 0; + private const int DebugInfo = 1; + private const int DebugVerbose = 2; + + /// + /// CWS base path + /// + public string BasePath { get; private set; } + + /// + /// Tracks if CWS is registered + /// + public bool IsRegistered + { + get { return _server.IsRegistered; } + } + + /// + /// Constructor + /// + /// + /// + /// + public EssemtialsWebApi(string key, string name, EssentialsWebApiPropertiesConfig config) + : base(key, name) + { + Key = key; + + BasePath = string.IsNullOrEmpty(config.BasePath) ? DefaultBasePath : config.BasePath; + + _server = new GenericCwsBase(Key, Name, BasePath); + } + + /// + /// Custom activate, add routes + /// + /// + public override bool CustomActivate() + { + var routes = new List + { + new HttpCwsRoute("reportversions") + { + Name = "ReportVersions", + RouteHandler = new ReportVersionsRequestHandler() + }, + new HttpCwsRoute("appdebug") + { + Name = "AppDebug", + RouteHandler = new AppDebugRequestHandler() + }, + new HttpCwsRoute("devlist") + { + Name = "DevList", + RouteHandler = new DevListRequestHandler() + }, + new HttpCwsRoute("devprops/{key}") + { + Name = "DevProps", + RouteHandler = new DevPropsRequestHandler() + }, + new HttpCwsRoute("devjson") + { + Name = "DevJson", + RouteHandler = new DevJsonRequestHandler() + }, + new HttpCwsRoute("setdevicestreamdebug/{deviceKey}/{state}") + { + Name = "SetDeviceStreamDebug", + RouteHandler = new SetDeviceStreamDebugRequestHandler() + }, + new HttpCwsRoute("disableallstreamdebug") + { + Name = "DisableAllStreamDebug", + RouteHandler = new DisableAllStreamDebugRequestHandler() + }, + new HttpCwsRoute("showconfig") + { + Name = "ShowConfig", + RouteHandler = new ShowConfigRequestHandler() + }, + new HttpCwsRoute("gettypes/all") + { + Name = "GetTypesAll", + RouteHandler = new GetTypesRequestHandler() + }, + new HttpCwsRoute("gettypes/{filter}") + { + Name = "GetTypesByFilter", + RouteHandler = new GetTypesRequestHandler() + }, + new HttpCwsRoute("getjoinmap/{bridgeKey}/all") + { + Name = "GetJoinMapsByBridgeKey", + RouteHandler = new GetJoinMapRequestHandler() + }, + new HttpCwsRoute("getjoinmap/{bridgeKey}/{deviceKey}") + { + Name = "GetJoinMapsForBridgeKeyFilteredByDeviceKey", + RouteHandler = new GetJoinMapRequestHandler() + } + }; + + foreach (var route in routes) + { + _server.AddRoute(route); + } + + return base.CustomActivate(); + } + + /// + /// Initializes the CWS class + /// + public override void Initialize() + { + // If running on an appliance + if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance) + { + /* + RMC4> + WEBSERVER [ON | OFF | TIMEOUT | MAXSESSIONSPERUSER ] + WEBSERVER [TIMEOUT] will display current session timeout value + WEBSERVER MAXSESSIONSPERUSER will display current max web sessions per user + WEBSERVER ALLOWSHAREDSESSION will display whether 'samesite = none' would be set on cookies + No parameter - displays current setting + */ + var response = string.Empty; + CrestronConsole.SendControlSystemCommand("webserver", ref response); + if (response.Contains("OFF")) return; + + var is4Series = eCrestronSeries.Series4 == (Global.ProcessorSeries & eCrestronSeries.Series4); + Debug.Console(DebugTrace, Debug.ErrorLogLevel.Notice, "Starting Essentials CWS on {0} Appliance", is4Series ? "4-series" : "3-series"); + + _server.Start(); + + return; + } + + // Automatically start CWS when running on a server (Linux OS, Virtual Control) + Debug.Console(DebugTrace, Debug.ErrorLogLevel.Notice, "Starting Essentials CWS on Virtual Control Server"); + + _server.Start(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiFactory.cs new file mode 100644 index 00000000..51361c2c --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiFactory.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using PepperDash.Core; +using PepperDash.Essentials.Core.Config; + +namespace PepperDash.Essentials.Core.Web +{ + public class EssentialsWebApiFactory : EssentialsDeviceFactory + { + public EssentialsWebApiFactory() + { + TypeNames = new List { "EssentialsWebApi" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new Essentials Web API Server"); + + var props = dc.Properties.ToObject(); + if (props != null) return new EssemtialsWebApi(dc.Key, dc.Name, props); + + Debug.Console(1, "Factory failed to create new Essentials Web API Server"); + return null; + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiPropertiesConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiPropertiesConfig.cs new file mode 100644 index 00000000..a57e1ce9 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiPropertiesConfig.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Core.Web +{ + public class EssentialsWebApiPropertiesConfig + { + [JsonProperty("basePath")] + public string BasePath { get; set; } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs new file mode 100644 index 00000000..0ec54343 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs @@ -0,0 +1,111 @@ +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class AppDebugRequestHandler : CwsBaseHandler + { + public AppDebugRequestHandler() + { + } + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs new file mode 100644 index 00000000..c5f76089 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs @@ -0,0 +1,111 @@ +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class DevJsonRequestHandler : CwsBaseHandler + { + public DevJsonRequestHandler() + { + } + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs new file mode 100644 index 00000000..2e8290fd --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs @@ -0,0 +1,111 @@ +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class DevListRequestHandler : CwsBaseHandler + { + public DevListRequestHandler() + { + } + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs new file mode 100644 index 00000000..e37bafa7 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs @@ -0,0 +1,111 @@ +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class DevPropsRequestHandler : CwsBaseHandler + { + public DevPropsRequestHandler() + { + } + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs new file mode 100644 index 00000000..8ddeebd6 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs @@ -0,0 +1,111 @@ +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class DisableAllStreamDebugRequestHandler : CwsBaseHandler + { + public DisableAllStreamDebugRequestHandler() + { + } + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs new file mode 100644 index 00000000..59c6ef4c --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs @@ -0,0 +1,111 @@ +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class GetJoinMapRequestHandler : CwsBaseHandler + { + public GetJoinMapRequestHandler() + { + } + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs new file mode 100644 index 00000000..f3761173 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs @@ -0,0 +1,111 @@ +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class GetTypesRequestHandler : CwsBaseHandler + { + public GetTypesRequestHandler() + { + } + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs new file mode 100644 index 00000000..dddf0e02 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs @@ -0,0 +1,111 @@ +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class ReportVersionsRequestHandler : CwsBaseHandler + { + public ReportVersionsRequestHandler() + { + } + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs new file mode 100644 index 00000000..146a0c1a --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs @@ -0,0 +1,111 @@ +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class SetDeviceStreamDebugRequestHandler : CwsBaseHandler + { + public SetDeviceStreamDebugRequestHandler() + { + } + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs new file mode 100644 index 00000000..ad28d26c --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs @@ -0,0 +1,111 @@ +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class ShowConfigRequestHandler : CwsBaseHandler + { + public ShowConfigRequestHandler() + { + } + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/packages.config b/packages.config index ffea92a5..aeeba3c1 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From f4a5d6737e1fc94e719f64832b3fe09ea33f0d0c Mon Sep 17 00:00:00 2001 From: jdevito Date: Thu, 19 Jan 2023 11:50:48 -0600 Subject: [PATCH 181/202] fix: updated packages.config reference for PepperDash_Core to latest WebAPI build --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index aeeba3c1..d7e637ee 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From 03d5c24dc46793e5a48be0ed0bebe2d0101e5da6 Mon Sep 17 00:00:00 2001 From: jdevito Date: Thu, 19 Jan 2023 12:00:32 -0600 Subject: [PATCH 182/202] fix: updated Essentials WebAPI and Request Handlers using statements to reflect PepperDash Core updates in 1.1.5-alpha-286 --- .../PepperDashEssentialsBase/Web/EssemtialsWebApi.cs | 5 +++-- .../Web/RequestHandlers/AppDebugRequestHandler.cs | 4 ++-- .../Web/RequestHandlers/DevJsonRequestHandler.cs | 4 ++-- .../Web/RequestHandlers/DevListRequestHandler.cs | 4 ++-- .../Web/RequestHandlers/DevPropsRequestHandler.cs | 4 ++-- .../RequestHandlers/DisableAllStreamDebugRequestHandler.cs | 4 ++-- .../Web/RequestHandlers/GetJoinMapRequestHandler.cs | 4 ++-- .../Web/RequestHandlers/GetTypesRequestHandler.cs | 4 ++-- .../Web/RequestHandlers/ReportVersionsRequestHandler.cs | 4 ++-- .../RequestHandlers/SetDeviceStreamDebugRequestHandler.cs | 4 ++-- .../Web/RequestHandlers/ShowConfigRequestHandler.cs | 4 ++-- 11 files changed, 23 insertions(+), 22 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs index 9e6fe64c..e069e7a6 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs @@ -2,13 +2,14 @@ using Crestron.SimplSharp; using Crestron.SimplSharp.WebScripting; using PepperDash.Core; +using PepperDash.Core.Web; using PepperDash.Essentials.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web { public class EssemtialsWebApi : EssentialsDevice { - private readonly GenericCwsBase _server; + private readonly WebApiServer _server; private const string DefaultBasePath = "/api"; @@ -42,7 +43,7 @@ namespace PepperDash.Essentials.Core.Web BasePath = string.IsNullOrEmpty(config.BasePath) ? DefaultBasePath : config.BasePath; - _server = new GenericCwsBase(Key, Name, BasePath); + _server = new WebApiServer(Key, Name, BasePath); } /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs index 0ec54343..e550b3f0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs @@ -1,9 +1,9 @@ using Crestron.SimplSharp.WebScripting; -using PepperDash.Core; +using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { - public class AppDebugRequestHandler : CwsBaseHandler + public class AppDebugRequestHandler : WebApiBaseRequestHandler { public AppDebugRequestHandler() { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs index c5f76089..c7206739 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs @@ -1,9 +1,9 @@ using Crestron.SimplSharp.WebScripting; -using PepperDash.Core; +using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { - public class DevJsonRequestHandler : CwsBaseHandler + public class DevJsonRequestHandler : WebApiBaseRequestHandler { public DevJsonRequestHandler() { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs index 2e8290fd..77cd9bbe 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs @@ -1,9 +1,9 @@ using Crestron.SimplSharp.WebScripting; -using PepperDash.Core; +using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { - public class DevListRequestHandler : CwsBaseHandler + public class DevListRequestHandler : WebApiBaseRequestHandler { public DevListRequestHandler() { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs index e37bafa7..d1cdb09a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs @@ -1,9 +1,9 @@ using Crestron.SimplSharp.WebScripting; -using PepperDash.Core; +using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { - public class DevPropsRequestHandler : CwsBaseHandler + public class DevPropsRequestHandler : WebApiBaseRequestHandler { public DevPropsRequestHandler() { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs index 8ddeebd6..fa93c5ff 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs @@ -1,9 +1,9 @@ using Crestron.SimplSharp.WebScripting; -using PepperDash.Core; +using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { - public class DisableAllStreamDebugRequestHandler : CwsBaseHandler + public class DisableAllStreamDebugRequestHandler : WebApiBaseRequestHandler { public DisableAllStreamDebugRequestHandler() { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs index 59c6ef4c..53abb868 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs @@ -1,9 +1,9 @@ using Crestron.SimplSharp.WebScripting; -using PepperDash.Core; +using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { - public class GetJoinMapRequestHandler : CwsBaseHandler + public class GetJoinMapRequestHandler : WebApiBaseRequestHandler { public GetJoinMapRequestHandler() { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs index f3761173..e2e8fc51 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs @@ -1,9 +1,9 @@ using Crestron.SimplSharp.WebScripting; -using PepperDash.Core; +using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { - public class GetTypesRequestHandler : CwsBaseHandler + public class GetTypesRequestHandler : WebApiBaseRequestHandler { public GetTypesRequestHandler() { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs index dddf0e02..a0e68722 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs @@ -1,9 +1,9 @@ using Crestron.SimplSharp.WebScripting; -using PepperDash.Core; +using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { - public class ReportVersionsRequestHandler : CwsBaseHandler + public class ReportVersionsRequestHandler : WebApiBaseRequestHandler { public ReportVersionsRequestHandler() { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs index 146a0c1a..4c485205 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs @@ -1,9 +1,9 @@ using Crestron.SimplSharp.WebScripting; -using PepperDash.Core; +using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { - public class SetDeviceStreamDebugRequestHandler : CwsBaseHandler + public class SetDeviceStreamDebugRequestHandler : WebApiBaseRequestHandler { public SetDeviceStreamDebugRequestHandler() { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs index ad28d26c..2a42c4a3 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs @@ -1,9 +1,9 @@ using Crestron.SimplSharp.WebScripting; -using PepperDash.Core; +using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { - public class ShowConfigRequestHandler : CwsBaseHandler + public class ShowConfigRequestHandler : WebApiBaseRequestHandler { public ShowConfigRequestHandler() { From 555944011d4c6cc3e57f2a955403b57aba567e68 Mon Sep 17 00:00:00 2001 From: jdevito Date: Thu, 19 Jan 2023 12:19:27 -0600 Subject: [PATCH 183/202] fix: added continue to resolve warning of possible empty statement when compiled locally --- .../PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs index 6ffb16cc..67a5740f 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs @@ -579,7 +579,7 @@ namespace PepperDash.Essentials.Core var errorKey = string.Empty; foreach (var item in dataArray) { - if (item.Value.TrimEnd() == placeholder) ; + if (item.Value.TrimEnd() == placeholder) continue; errorKey = item.Key; break; } From 0c2896f9aa0142b641b7c4801988ea94c26f1148 Mon Sep 17 00:00:00 2001 From: jdevito Date: Tue, 24 Jan 2023 12:22:40 -0600 Subject: [PATCH 184/202] fix: updated packages.config to reference PepperDashCore.1.1.5-alpha-291, built on latest development branch; removed empty constructor from request handlers --- .../PepperDashEssentialsBase/Comm and IR/CommFactory.cs | 2 ++ .../Web/RequestHandlers/AppDebugRequestHandler.cs | 4 ---- .../Web/RequestHandlers/DevJsonRequestHandler.cs | 4 ---- .../Web/RequestHandlers/DevListRequestHandler.cs | 4 ---- .../Web/RequestHandlers/DevPropsRequestHandler.cs | 4 ---- .../RequestHandlers/DisableAllStreamDebugRequestHandler.cs | 4 ---- .../Web/RequestHandlers/GetJoinMapRequestHandler.cs | 4 ---- .../Web/RequestHandlers/GetTypesRequestHandler.cs | 4 ---- .../Web/RequestHandlers/ReportVersionsRequestHandler.cs | 4 ---- .../Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs | 4 ---- .../Web/RequestHandlers/ShowConfigRequestHandler.cs | 4 ---- packages.config | 2 +- 12 files changed, 3 insertions(+), 41 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs index 8a5efe47..9667b5b9 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs @@ -183,6 +183,8 @@ namespace PepperDash.Essentials.Core [JsonConverter(typeof(ComSpecJsonConverter))] public ComPort.ComPortSpec ComParams { get; set; } + public string RoomId { get; set; } + public string CresnetId { get; set; } /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs index e550b3f0..ef19e2d5 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs @@ -5,10 +5,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class AppDebugRequestHandler : WebApiBaseRequestHandler { - public AppDebugRequestHandler() - { - } - /// /// Handles CONNECT method requests /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs index c7206739..ea7b0d0f 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs @@ -5,10 +5,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DevJsonRequestHandler : WebApiBaseRequestHandler { - public DevJsonRequestHandler() - { - } - /// /// Handles CONNECT method requests /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs index 77cd9bbe..2bccc435 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs @@ -5,10 +5,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DevListRequestHandler : WebApiBaseRequestHandler { - public DevListRequestHandler() - { - } - /// /// Handles CONNECT method requests /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs index d1cdb09a..08eb6853 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs @@ -5,10 +5,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DevPropsRequestHandler : WebApiBaseRequestHandler { - public DevPropsRequestHandler() - { - } - /// /// Handles CONNECT method requests /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs index fa93c5ff..489bfd55 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs @@ -5,10 +5,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DisableAllStreamDebugRequestHandler : WebApiBaseRequestHandler { - public DisableAllStreamDebugRequestHandler() - { - } - /// /// Handles CONNECT method requests /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs index 53abb868..c08846e2 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs @@ -5,10 +5,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class GetJoinMapRequestHandler : WebApiBaseRequestHandler { - public GetJoinMapRequestHandler() - { - } - /// /// Handles CONNECT method requests /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs index e2e8fc51..ce33866d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs @@ -5,10 +5,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class GetTypesRequestHandler : WebApiBaseRequestHandler { - public GetTypesRequestHandler() - { - } - /// /// Handles CONNECT method requests /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs index a0e68722..2ee3fec4 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs @@ -5,10 +5,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class ReportVersionsRequestHandler : WebApiBaseRequestHandler { - public ReportVersionsRequestHandler() - { - } - /// /// Handles CONNECT method requests /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs index 4c485205..58280f57 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs @@ -5,10 +5,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class SetDeviceStreamDebugRequestHandler : WebApiBaseRequestHandler { - public SetDeviceStreamDebugRequestHandler() - { - } - /// /// Handles CONNECT method requests /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs index 2a42c4a3..5edb50da 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs @@ -5,10 +5,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class ShowConfigRequestHandler : WebApiBaseRequestHandler { - public ShowConfigRequestHandler() - { - } - /// /// Handles CONNECT method requests /// diff --git a/packages.config b/packages.config index d7e637ee..87f5b8c1 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file From 1bae7dc91bc1c417102dfcdd1188790ab6374f8e Mon Sep 17 00:00:00 2001 From: jta Date: Mon, 30 Jan 2023 15:19:14 -0500 Subject: [PATCH 185/202] feature: add workflow to push to project --- .github/workflows/add-issues-to-project.yml | 37 +++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/add-issues-to-project.yml diff --git a/.github/workflows/add-issues-to-project.yml b/.github/workflows/add-issues-to-project.yml new file mode 100644 index 00000000..8811c0cc --- /dev/null +++ b/.github/workflows/add-issues-to-project.yml @@ -0,0 +1,37 @@ +name: Add bugs to bugs project + +on: + issues: + types: + - opened + - labeled + +jobs: + check-secret: + runs-on: ubuntu-latest + outputs: + my-key: ${{ steps.my-key.outputs.defined }} + steps: + - id: my-key + if: "${{ env.MY_KEY != '' }}" + run: echo "::set-output name=defined::true" + env: + MY_KEY: ${{ secrets.PROJECT_URL }} + throw-error: + name: Check + runs-on: ubuntu-latest + needs: [check-secret] + if: needs.check-secret.outputs.my-key != 'true' + steps: + - run: echo "The Project URL Repo Secret is empty" + add-to-project: + name: Add issue to project + runs-on: ubuntu-latest + needs: [check-secret] + if: needs.check-secret.outputs.my-key == 'true' + steps: + - uses: actions/add-to-project@main + with: + project-url: ${{ secrets.PROJECT_URL }} + github-token: ${{ secrets.GH_PROJECTS_PASSWORD }} + From 705e750419262a1328035fa2344263a179ebf61c Mon Sep 17 00:00:00 2001 From: jdevito Date: Mon, 30 Jan 2023 17:17:12 -0600 Subject: [PATCH 186/202] fix: resolved issue with default handlers, removed debug statements that were not accessed; fix: updated default handler, reportversions handler, devlist handler --- PepperDashEssentials/ControlSystem.cs | 2 + .../PepperDash_Essentials_Core.csproj | 1 + .../Web/EssemtialsWebApi.cs | 82 +++++++++++-- .../RequestHandlers/DefaultRequestHandler.cs | 112 ++++++++++++++++++ .../RequestHandlers/DevListRequestHandler.cs | 39 +++++- .../ReportVersionsRequestHandler.cs | 33 +++++- 6 files changed, 254 insertions(+), 15 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DefaultRequestHandler.cs diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index 1ab3b28e..736a250f 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -13,6 +13,7 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Fusion; +using PepperDash.Essentials.Core.Web; using PepperDash.Essentials.Devices.Common; using PepperDash.Essentials.DM; using PepperDash.Essentials.Fusion; @@ -353,6 +354,7 @@ namespace PepperDash.Essentials // Build the processor wrapper class DeviceManager.AddDevice(new PepperDash.Essentials.Core.Devices.CrestronProcessor("processor")); + DeviceManager.AddDevice(new EssemtialsWebApi("essentialsWebApi","Essentials Web API")); // Add global System Monitor device if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index fb861df6..077bdac9 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -198,6 +198,7 @@ + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs index e069e7a6..f708d011 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs @@ -1,6 +1,11 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; using Crestron.SimplSharp; using Crestron.SimplSharp.WebScripting; +using Crestron.SimplSharpPro.Diagnostics; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using PepperDash.Core; using PepperDash.Core.Web; using PepperDash.Essentials.Core.Web.RequestHandlers; @@ -11,11 +16,17 @@ namespace PepperDash.Essentials.Core.Web { private readonly WebApiServer _server; - private const string DefaultBasePath = "/api"; + /// + /// http(s)://{ipaddress}/cws/{basePath} + /// http(s)://{ipaddress}/VirtualControl/Rooms/{roomId}/cws/{basePath} + /// + private readonly string _defaultBasePath = + CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? string.Format("/app{0:00}/api", InitialParametersClass.ApplicationNumber) : "/api"; + // TODO [ ] Reset debug levels to proper value Trace = 0, Info = 1, Verbose = 2 private const int DebugTrace = 0; - private const int DebugInfo = 1; - private const int DebugVerbose = 2; + private const int DebugInfo = 0; + private const int DebugVerbose = 0; /// /// CWS base path @@ -30,6 +41,16 @@ namespace PepperDash.Essentials.Core.Web get { return _server.IsRegistered; } } + /// + /// Constructor + /// + /// + /// + public EssemtialsWebApi(string key, string name) + : this(key, name, null) + { + } + /// /// Constructor /// @@ -41,7 +62,10 @@ namespace PepperDash.Essentials.Core.Web { Key = key; - BasePath = string.IsNullOrEmpty(config.BasePath) ? DefaultBasePath : config.BasePath; + if (config == null) + BasePath = _defaultBasePath; + else + BasePath = string.IsNullOrEmpty(config.BasePath) ? _defaultBasePath : config.BasePath; _server = new WebApiServer(Key, Name, BasePath); } @@ -116,9 +140,10 @@ namespace PepperDash.Essentials.Core.Web } }; - foreach (var route in routes) + foreach (var route in routes.Where(route => route != null)) { - _server.AddRoute(route); + var r = route; + _server.AddRoute(r); } return base.CustomActivate(); @@ -145,17 +170,56 @@ namespace PepperDash.Essentials.Core.Web if (response.Contains("OFF")) return; var is4Series = eCrestronSeries.Series4 == (Global.ProcessorSeries & eCrestronSeries.Series4); - Debug.Console(DebugTrace, Debug.ErrorLogLevel.Notice, "Starting Essentials CWS on {0} Appliance", is4Series ? "4-series" : "3-series"); + Debug.Console(DebugTrace, Debug.ErrorLogLevel.Notice, "Starting Essentials Web API on {0} Appliance", is4Series ? "4-series" : "3-series"); _server.Start(); + GetPaths(); + return; } // Automatically start CWS when running on a server (Linux OS, Virtual Control) - Debug.Console(DebugTrace, Debug.ErrorLogLevel.Notice, "Starting Essentials CWS on Virtual Control Server"); + Debug.Console(DebugTrace, Debug.ErrorLogLevel.Notice, "Starting Essentials Web API on Virtual Control Server"); _server.Start(); } + + /// + /// Print the available pahts + /// + /// + /// http(s)://{ipaddress}/cws/{basePath} + /// http(s)://{ipaddress}/VirtualControl/Rooms/{roomId}/cws/{basePath} + /// + public void GetPaths() + { + Debug.Console(DebugTrace, this, "{0}", new String('-', 50)); + + var currentIp = CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0); + + var hostname = CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0); + + var path = CrestronEnvironment.DevicePlatform == eDevicePlatform.Server + ? string.Format("http(s)://{0}/virtualcontrol/rooms/{1}/cws{2}", hostname, InitialParametersClass.RoomId, BasePath) + : string.Format("http(s)://{0}/cws{1}", currentIp, BasePath); + + Debug.Console(DebugTrace, this, "Server:{0}", path); + + var routeCollection = _server.GetRouteCollection(); + if (routeCollection == null) + { + Debug.Console(DebugTrace, this, "Server route collection is null"); + return; + } + Debug.Console(DebugTrace, this, "Configured Routes:"); + foreach (var route in routeCollection) + { + Debug.Console(DebugTrace, this, "{0}: {1}/{2}", route.Name, path, route.Url); + } + Debug.Console(DebugTrace, this, "{0}", new String('-', 50)); + } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DefaultRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DefaultRequestHandler.cs new file mode 100644 index 00000000..2cd55d4d --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DefaultRequestHandler.cs @@ -0,0 +1,112 @@ +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core.Web.RequestHandlers; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class DefaultRequestHandler : WebApiBaseRequestHandler + { + private const string Key = "DefaultRequestHandler"; + private const uint Trace = 0; + private const uint Info = 1; + private const uint Verbose = 2; + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs index 2bccc435..cc7a1528 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs @@ -1,10 +1,20 @@ -using Crestron.SimplSharp.WebScripting; +using System.Diagnostics; +using System.Linq; +using Crestron.SimplSharp.WebScripting; +using Newtonsoft.Json; +using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; +using Debug = PepperDash.Core.Debug; namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DevListRequestHandler : WebApiBaseRequestHandler { + private const string Key = "DevListRequestHandler"; + private const uint Trace = 0; + private const uint Info = 0; + private const uint Verbose = 0; + /// /// Handles CONNECT method requests /// @@ -33,8 +43,31 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleGet(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + var allDevices = DeviceManager.AllDevices; + allDevices.Sort((a, b) => System.String.Compare(a.Key, b.Key, System.StringComparison.Ordinal)); + + var devices = allDevices.Select(device => new + { + Key = device.Key, + Name = device is IKeyName ? (device as IKeyName).Name : "---" + + }).Cast().ToList(); + + var js = JsonConvert.SerializeObject(devices, Formatting.Indented, new JsonSerializerSettings + { + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + NullValueHandling = NullValueHandling.Ignore, + MissingMemberHandling = MissingMemberHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore, + TypeNameHandling = TypeNameHandling.None + }); + //Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = System.Text.Encoding.UTF8; + context.Response.Write(js, false); context.Response.End(); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs index 2ee3fec4..a8b36eb5 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs @@ -1,10 +1,18 @@ -using Crestron.SimplSharp.WebScripting; +using System.Linq; +using Crestron.SimplSharp.WebScripting; +using Newtonsoft.Json; +using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class ReportVersionsRequestHandler : WebApiBaseRequestHandler { + private const string Key = "ReportVersionsRequestHandler"; + private const uint Trace = 0; + private const uint Info = 0; + private const uint Verbose = 0; + /// /// Handles CONNECT method requests /// @@ -33,8 +41,27 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleGet(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + var assemblies = PluginLoader.LoadedAssemblies.Select(assembly => new + { + Name = assembly.Name, + Version = assembly.Version + }).Cast().ToList(); + + var js = JsonConvert.SerializeObject(assemblies, Formatting.Indented, new JsonSerializerSettings + { + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + NullValueHandling = NullValueHandling.Ignore, + MissingMemberHandling = MissingMemberHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore, + TypeNameHandling = TypeNameHandling.None + }); + //Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = System.Text.Encoding.UTF8; + context.Response.Write(js, false); context.Response.End(); } From dd2aca9aa472a8fa9370362e2a2ecf0c3e7c852c Mon Sep 17 00:00:00 2001 From: jdevito Date: Mon, 30 Jan 2023 22:08:13 -0600 Subject: [PATCH 187/202] feat: worked on adding get/post for appdebug, devprops, devjson, disableallstreamdebug, setdevicestreamdebug --- .../Room/Types/EssentialsTechRoom.cs | 2 +- .../Web/EssemtialsWebApi.cs | 18 +++++-- .../RequestHandlers/AppDebugRequestHandler.cs | 48 +++++++++++++++++-- .../RequestHandlers/DevJsonRequestHandler.cs | 23 +++++++-- .../RequestHandlers/DevListRequestHandler.cs | 4 +- .../RequestHandlers/DevPropsRequestHandler.cs | 41 ++++++++++++++-- .../DisableAllStreamDebugRequestHandler.cs | 6 ++- .../ReportVersionsRequestHandler.cs | 1 - .../SetDeviceStreamDebugRequestHandler.cs | 47 ++++++++++++++++-- 9 files changed, 165 insertions(+), 25 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsTechRoom.cs b/PepperDashEssentials/Room/Types/EssentialsTechRoom.cs index b97ef9c4..65cc52fa 100644 --- a/PepperDashEssentials/Room/Types/EssentialsTechRoom.cs +++ b/PepperDashEssentials/Room/Types/EssentialsTechRoom.cs @@ -272,7 +272,7 @@ namespace PepperDash.Essentials { Debug.Console(2, this, @"Attempting to run action: -DeviceKey: {0} +Key: {0} MethodName: {1} Params: {2}" , a.DeviceKey, a.MethodName, a.Params); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs index f708d011..8b0f7c86 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs @@ -93,21 +93,31 @@ namespace PepperDash.Essentials.Core.Web Name = "DevList", RouteHandler = new DevListRequestHandler() }, - new HttpCwsRoute("devprops/{key}") + new HttpCwsRoute("devprops") { Name = "DevProps", RouteHandler = new DevPropsRequestHandler() }, + //new HttpCwsRoute("devprops/{key}") + //{ + // Name = "DevProps", + // RouteHandler = new DevPropsRequestHandler() + //}, new HttpCwsRoute("devjson") { Name = "DevJson", RouteHandler = new DevJsonRequestHandler() }, - new HttpCwsRoute("setdevicestreamdebug/{deviceKey}/{state}") + new HttpCwsRoute("setdevicestreamdebug") { - Name = "SetDeviceStreamDebug", - RouteHandler = new SetDeviceStreamDebugRequestHandler() + Name = "SetDeviceStreamDebug", + RouteHandler = new SetDeviceStreamDebugRequestHandler() }, + //new HttpCwsRoute("setdevicestreamdebug/{deviceKey}/{state}") + //{ + // Name = "SetDeviceStreamDebug", + // RouteHandler = new SetDeviceStreamDebugRequestHandler() + //}, new HttpCwsRoute("disableallstreamdebug") { Name = "DisableAllStreamDebug", diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs index ef19e2d5..f88ae849 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs @@ -1,10 +1,19 @@ -using Crestron.SimplSharp.WebScripting; +using System; +using System.Text; +using Crestron.SimplSharp.WebScripting; +using Newtonsoft.Json; +using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class AppDebugRequestHandler : WebApiBaseRequestHandler { + private const string Key = "AppDebugRequestHandler"; + private const uint Trace = 0; + private const uint Info = 0; + private const uint Verbose = 0; + /// /// Handles CONNECT method requests /// @@ -33,8 +42,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleGet(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + var o = new AppDebug(); + o.Level = Debug.Level; + + var body = JsonConvert.SerializeObject(o, Formatting.Indented); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.Write(body, false); context.Response.End(); } @@ -77,8 +92,25 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandlePost(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + if (context.Request.ContentLength < 0) return; + + var bytes = new Byte[context.Request.ContentLength]; + context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); + var data = Encoding.UTF8.GetString(bytes, 0, bytes.Length); + //Debug.Console(Info, "[{0}] Request data:\n{1}", Key.ToLower(), data); + + var o = new AppDebug(); + var requestBody = JsonConvert.DeserializeAnonymousType(data, o); + + Debug.SetDebugLevel(requestBody.Level); + + o.Level = Debug.Level; + + var responseBody = JsonConvert.SerializeObject(o, Formatting.Indented); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.Write(responseBody, false); context.Response.End(); } @@ -104,4 +136,10 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.End(); } } + + public class AppDebug + { + [JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)] + public int Level { get; set; } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs index ea7b0d0f..fb9e8261 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs @@ -1,10 +1,18 @@ -using Crestron.SimplSharp.WebScripting; +using System; +using System.Text; +using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DevJsonRequestHandler : WebApiBaseRequestHandler { + private const string Key = "DevJsonRequestHandler"; + private const uint Trace = 0; + private const uint Info = 0; + private const uint Verbose = 0; + /// /// Handles CONNECT method requests /// @@ -77,8 +85,17 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandlePost(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + if (context.Request.ContentLength < 0) return; + + var bytes = new Byte[context.Request.ContentLength]; + context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); + var data = Encoding.UTF8.GetString(bytes, 0, bytes.Length); + Debug.Console(Info, "[{0}] Request data:\n{1}", Key.ToLower(), data); + + DeviceJsonApi.DoDeviceActionWithJson(data); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; context.Response.End(); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs index cc7a1528..faa0fff3 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs @@ -1,10 +1,8 @@ -using System.Diagnostics; -using System.Linq; +using System.Linq; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; -using Debug = PepperDash.Core.Debug; namespace PepperDash.Essentials.Core.Web.RequestHandlers { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs index 08eb6853..34ab4f77 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs @@ -1,10 +1,19 @@ -using Crestron.SimplSharp.WebScripting; +using System; +using System.Text; +using Crestron.SimplSharp.WebScripting; +using Newtonsoft.Json; +using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DevPropsRequestHandler : WebApiBaseRequestHandler { + private const string Key = "DevPropsRequestHandler"; + private const uint Trace = 0; + private const uint Info = 0; + private const uint Verbose = 0; + /// /// Handles CONNECT method requests /// @@ -77,8 +86,34 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandlePost(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + if (context.Request.ContentLength < 0) return; + + var bytes = new Byte[context.Request.ContentLength]; + context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); + var data = Encoding.UTF8.GetString(bytes, 0, bytes.Length); + //Debug.Console(Info, "[{0}] Request data:\n{1}", Key.ToLower(), data); + + var o = new DeviceActionWrapper(); + var body = JsonConvert.DeserializeAnonymousType(data, o); + + if (string.IsNullOrEmpty(body.DeviceKey)) + { + Debug.Console(Info, "[{0}] Request body is null or empty", Key.ToLower()); + + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + var deviceProps = DeviceJsonApi.GetProperties(body.DeviceKey); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = Encoding.UTF8; + context.Response.Write(deviceProps, false); context.Response.End(); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs index 489bfd55..8cfc7315 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs @@ -77,8 +77,10 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandlePost(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + DeviceManager.DisableAllDeviceStreamDebugging(); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; context.Response.End(); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs index a8b36eb5..ab0e4d8d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs @@ -1,7 +1,6 @@ using System.Linq; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; -using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs index 58280f57..ce026b04 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs @@ -1,10 +1,20 @@ -using Crestron.SimplSharp.WebScripting; +using System; +using System.Text; +using Crestron.SimplSharp.WebScripting; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class SetDeviceStreamDebugRequestHandler : WebApiBaseRequestHandler { + private const string Key = "SetDeviceStreamDebugRequestHandler"; + private const uint Trace = 0; + private const uint Info = 0; + private const uint Verbose = 0; + /// /// Handles CONNECT method requests /// @@ -77,8 +87,39 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandlePost(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + if (context.Request.ContentLength < 0) return; + + var bytes = new Byte[context.Request.ContentLength]; + context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); + var data = Encoding.UTF8.GetString(bytes, 0, bytes.Length); + Debug.Console(Info, "[{0}] Request data:\n{1}", Key.ToLower(), data); + + var o = new + { + DeviceKey = "", + Type = "", + Timeout = 15 + }; + + var body = JsonConvert.DeserializeAnonymousType(data, o); + + if (string.IsNullOrEmpty(body.DeviceKey) || string.IsNullOrEmpty(body.Type) + || !body.Type.ToLower().Contains("off") + || !body.Type.ToLower().Contains("tx") + || !body.Type.ToLower().Contains("rx") + || !body.Type.ToLower().Contains("both")) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + DeviceManager.SetDeviceStreamDebugging(string.Format("setdevicestreamdebug {0} {1} {2}", body.DeviceKey, body.Type, body.Timeout)); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; context.Response.End(); } From c68d46f9713be87cc322401443bf868c56265ba5 Mon Sep 17 00:00:00 2001 From: jdevito Date: Tue, 31 Jan 2023 18:27:14 -0600 Subject: [PATCH 188/202] fix: Updated showconfig, gettypes, getjoinmap handlers; updated BridgeBase to expose joinmaps; updated DeviceFactory to introduce method for getting dictionary --- .../Bridges/BridgeBase.cs | 2 +- .../Factory/DeviceFactory.cs | 12 ++ .../PepperDash_Essentials_Core.csproj | 4 +- .../Web/EssemtialsWebApi.cs | 16 +- .../RequestHandlers/DevJsonRequestHandler.cs | 17 +- .../GetJoinMapForBridgeKeyRequestHandler.cs | 175 ++++++++++++++++ .../GetJoinMapForDeviceKeyRequestHandler.cs | 196 ++++++++++++++++++ ...r.cs => GetTypesByFilterRequestHandler.cs} | 66 +++++- .../RequestHandlers/GetTypesRequestHandler.cs | 43 +++- .../SetDeviceStreamDebugRequestHandler.cs | 1 - .../ShowConfigRequestHandler.cs | 16 +- 11 files changed, 525 insertions(+), 23 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs rename essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/{GetJoinMapRequestHandler.cs => GetTypesByFilterRequestHandler.cs} (56%) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs index 11b8f4ff..cb937235 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs @@ -109,7 +109,7 @@ namespace PepperDash.Essentials.Core.Bridges { public EiscApiPropertiesConfig PropertiesConfig { get; private set; } - protected Dictionary JoinMaps { get; private set; } + public Dictionary JoinMaps { get; private set; } public BasicTriList Eisc { get; private set; } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs index ebdc87b1..9cbd8731 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs @@ -204,5 +204,17 @@ namespace PepperDash.Essentials.Core Description: {2}", type.Key, cType, description); } } + + /// + /// Returns the device factory dictionary + /// + /// + /// + public static Dictionary GetDeviceFactoryDictionary(string filter) + { + return !string.IsNullOrEmpty(filter) + ? FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value) + : FactoryMethods; + } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 077bdac9..4742a04f 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -198,6 +198,8 @@ + + @@ -206,7 +208,7 @@ - + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs index 8b0f7c86..149cc021 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs @@ -128,25 +128,25 @@ namespace PepperDash.Essentials.Core.Web Name = "ShowConfig", RouteHandler = new ShowConfigRequestHandler() }, - new HttpCwsRoute("gettypes/all") + new HttpCwsRoute("gettypes") { - Name = "GetTypesAll", + Name = "GetTypes", RouteHandler = new GetTypesRequestHandler() }, new HttpCwsRoute("gettypes/{filter}") { Name = "GetTypesByFilter", - RouteHandler = new GetTypesRequestHandler() + RouteHandler = new GetTypesByFilterRequestHandler() }, - new HttpCwsRoute("getjoinmap/{bridgeKey}/all") + new HttpCwsRoute("getjoinmap/{bridgeKey}") { - Name = "GetJoinMapsByBridgeKey", - RouteHandler = new GetJoinMapRequestHandler() + Name = "GetJoinMapsForBridgeKey", + RouteHandler = new GetJoinMapForBridgeKeyRequestHandler() }, new HttpCwsRoute("getjoinmap/{bridgeKey}/{deviceKey}") { - Name = "GetJoinMapsForBridgeKeyFilteredByDeviceKey", - RouteHandler = new GetJoinMapRequestHandler() + Name = "GetJoinMapsForDeviceKey", + RouteHandler = new GetJoinMapForDeviceKeyRequestHandler() } }; diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs index fb9e8261..d4cdac38 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs @@ -92,11 +92,20 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers var data = Encoding.UTF8.GetString(bytes, 0, bytes.Length); Debug.Console(Info, "[{0}] Request data:\n{1}", Key.ToLower(), data); - DeviceJsonApi.DoDeviceActionWithJson(data); + try + { + DeviceJsonApi.DoDeviceActionWithJson(data); - context.Response.StatusCode = 200; - context.Response.StatusDescription = "OK"; - context.Response.End(); + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.End(); + } + catch (Exception ex) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + } } /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs new file mode 100644 index 00000000..0421266f --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs @@ -0,0 +1,175 @@ +using Crestron.SimplSharp.WebScripting; +using Newtonsoft.Json; +using PepperDash.Core; +using PepperDash.Core.Web.RequestHandlers; +using PepperDash.Essentials.Core.Bridges; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class GetJoinMapForBridgeKeyRequestHandler : WebApiBaseRequestHandler + { + private const string Key = "GetJoinMapForBridgeKeyRequestHandler"; + private const uint Trace = 0; + private const uint Info = 0; + private const uint Verbose = 0; + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + var routeData = context.Request.RouteData; + if (routeData == null) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + + var routeDataJson = JsonConvert.SerializeObject(routeData, Formatting.Indented); + Debug.Console(Verbose, "routeData:\n{0}", routeDataJson); + + + object bridgeObj; + if (!routeData.Values.TryGetValue("bridgeKey", out bridgeObj)) + { + Debug.Console(Verbose, "TryGetValue bridgeKey failed"); + + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + var bridge = DeviceManager.GetDeviceForKey(bridgeObj.ToString()) as EiscApiAdvanced; + if (bridge == null) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + var joinMap = bridge.JoinMaps; + if (joinMap == null) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + var js = JsonConvert.SerializeObject(joinMap, Formatting.Indented, new JsonSerializerSettings + { + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + NullValueHandling = NullValueHandling.Ignore, + MissingMemberHandling = MissingMemberHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore, + TypeNameHandling = TypeNameHandling.None + }); + Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = System.Text.Encoding.UTF8; + context.Response.Write(js, false); + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs new file mode 100644 index 00000000..863e3d29 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs @@ -0,0 +1,196 @@ +using System.Collections.Generic; +using Crestron.SimplSharp.WebScripting; +using Newtonsoft.Json; +using PepperDash.Core; +using PepperDash.Core.Web.RequestHandlers; +using PepperDash.Essentials.Core.Bridges; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class GetJoinMapForDeviceKeyRequestHandler : WebApiBaseRequestHandler + { + private const string Key = "GetJoinMapForDeviceKeyRequestHandler"; + private const uint Trace = 0; + private const uint Info = 0; + private const uint Verbose = 0; + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + var routeData = context.Request.RouteData; + if (routeData == null) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + + var routeDataJson = JsonConvert.SerializeObject(routeData, Formatting.Indented); + Debug.Console(Verbose, "routeData:\n{0}", routeDataJson); + + + object bridgeObj; + if (!routeData.Values.TryGetValue("bridgeKey", out bridgeObj)) + { + Debug.Console(Verbose, "TryGetValue bridgeKey failed"); + + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + object deviceObj; + if (!routeData.Values.TryGetValue("deviceKey", out deviceObj)) + { + Debug.Console(Verbose, "TryGetValue deviceKey failed"); + + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + var bridge = DeviceManager.GetDeviceForKey(bridgeObj.ToString()) as EiscApiAdvanced; + if (bridge == null) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + JoinMapBaseAdvanced deviceJoinMap; + if (!bridge.JoinMaps.TryGetValue(deviceObj.ToString(), out deviceJoinMap)) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + var joinMap = new Dictionary + { + { + deviceObj.ToString(), + deviceJoinMap + } + }; + + var js = JsonConvert.SerializeObject(joinMap, Formatting.Indented, new JsonSerializerSettings + { + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + NullValueHandling = NullValueHandling.Ignore, + MissingMemberHandling = MissingMemberHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore, + TypeNameHandling = TypeNameHandling.None + }); + Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = System.Text.Encoding.UTF8; + context.Response.Write(js, false); + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs similarity index 56% rename from essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs rename to essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs index c08846e2..42cf84c0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs @@ -1,10 +1,18 @@ using Crestron.SimplSharp.WebScripting; +using Newtonsoft.Json; +using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; +using PepperDash.Essentials.Core.Bridges; namespace PepperDash.Essentials.Core.Web.RequestHandlers { - public class GetJoinMapRequestHandler : WebApiBaseRequestHandler + public class GetTypesByFilterRequestHandler : WebApiBaseRequestHandler { + private const string Key = "GetTypesByFilterRequestHandler"; + private const uint Trace = 0; + private const uint Info = 0; + private const uint Verbose = 0; + /// /// Handles CONNECT method requests /// @@ -33,8 +41,60 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleGet(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + var routeData = context.Request.RouteData; + if (routeData == null) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + + var routeDataJson = JsonConvert.SerializeObject(routeData, Formatting.Indented); + Debug.Console(Verbose, "routeData:\n{0}", routeDataJson); + + + object filterObj; + if (!routeData.Values.TryGetValue("filter", out filterObj)) + { + Debug.Console(Verbose, "TryGetValue filter failed"); + + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + var types = DeviceFactory.GetDeviceFactoryDictionary(filterObj.ToString()); + if (types == null) + { + Debug.Console(Verbose, "Get device type from dictionary failed"); + + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + var js = JsonConvert.SerializeObject(types, Formatting.Indented, new JsonSerializerSettings + { + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + NullValueHandling = NullValueHandling.Ignore, + MissingMemberHandling = MissingMemberHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore, + TypeNameHandling = TypeNameHandling.None + }); + Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = System.Text.Encoding.UTF8; + context.Response.Write(js, false); context.Response.End(); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs index ce33866d..bd1b967a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs @@ -1,10 +1,18 @@ -using Crestron.SimplSharp.WebScripting; +using System.Linq; +using Crestron.SimplSharp.WebScripting; +using Newtonsoft.Json; +using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class GetTypesRequestHandler : WebApiBaseRequestHandler { + private const string Key = "GetTypesRequestHandler"; + private const uint Trace = 0; + private const uint Info = 0; + private const uint Verbose = 0; + /// /// Handles CONNECT method requests /// @@ -33,8 +41,37 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleGet(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + // TODO [ ] DeviceFactory.FactoryMethods dictionary is private and the method GetDeviceFactoryTypes has a return type void + // added new public method to return the DeviceFactory.FactoryMethod dictionary + var types = DeviceFactory.GetDeviceFactoryDictionary(null); + if (types == null) + { + Debug.Console(Verbose, "Get device factory dictionary failed"); + + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + types.OrderBy(t => t.Key); + + var js = JsonConvert.SerializeObject(types, Formatting.Indented, new JsonSerializerSettings + { + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + NullValueHandling = NullValueHandling.Ignore, + MissingMemberHandling = MissingMemberHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore, + TypeNameHandling = TypeNameHandling.None + }); + //Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = System.Text.Encoding.UTF8; + context.Response.Write(js, false); context.Response.End(); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs index ce026b04..989cb663 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs @@ -2,7 +2,6 @@ using System.Text; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs index 5edb50da..e8621e33 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs @@ -1,10 +1,17 @@ using Crestron.SimplSharp.WebScripting; +using Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; +using PepperDash.Essentials.Core.Config; namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class ShowConfigRequestHandler : WebApiBaseRequestHandler { + private const string Key = "ShowConfigRequestHandler"; + private const uint Trace = 0; + private const uint Info = 0; + private const uint Verbose = 0; + /// /// Handles CONNECT method requests /// @@ -33,8 +40,13 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleGet(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + var config = JsonConvert.SerializeObject(ConfigReader.ConfigObject, Formatting.Indented); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = System.Text.Encoding.UTF8; + context.Response.Write(config, false); context.Response.End(); } From 15efed02a5332231eabdb69eec68d5a6d1375308 Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 1 Feb 2023 09:43:52 -0600 Subject: [PATCH 189/202] fix: resolved issue with GetTypes request handlers causing a 500 error response; updated debug constants to default levels --- .../Factory/DeviceFactory.cs | 6 +- .../RequestHandlers/AppDebugRequestHandler.cs | 4 +- .../RequestHandlers/DefaultRequestHandler.cs | 36 +++++----- .../RequestHandlers/DevJsonRequestHandler.cs | 4 +- .../RequestHandlers/DevListRequestHandler.cs | 4 +- .../RequestHandlers/DevPropsRequestHandler.cs | 4 +- .../DisableAllStreamDebugRequestHandler.cs | 5 ++ .../GetJoinMapForBridgeKeyRequestHandler.cs | 4 +- .../GetJoinMapForDeviceKeyRequestHandler.cs | 4 +- .../GetTypesByFilterRequestHandler.cs | 57 ++++++++------- .../RequestHandlers/GetTypesRequestHandler.cs | 69 ++++++++++++------- .../ReportVersionsRequestHandler.cs | 4 +- .../SetDeviceStreamDebugRequestHandler.cs | 4 +- .../ShowConfigRequestHandler.cs | 4 +- 14 files changed, 122 insertions(+), 87 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs index 9cbd8731..bad3e531 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs @@ -212,9 +212,9 @@ namespace PepperDash.Essentials.Core /// public static Dictionary GetDeviceFactoryDictionary(string filter) { - return !string.IsNullOrEmpty(filter) - ? FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value) - : FactoryMethods; + return string.IsNullOrEmpty(filter) + ? FactoryMethods + : FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value); } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs index f88ae849..ad413b7f 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs @@ -11,8 +11,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { private const string Key = "AppDebugRequestHandler"; private const uint Trace = 0; - private const uint Info = 0; - private const uint Verbose = 0; + private const uint Info = 1; + private const uint Verbose = 2; /// /// Handles CONNECT method requests diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DefaultRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DefaultRequestHandler.cs index 2cd55d4d..19bc8cb3 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DefaultRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DefaultRequestHandler.cs @@ -16,8 +16,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleConnect(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + context.Response.StatusCode = 418; + context.Response.StatusDescription = "I'm a teapot"; context.Response.End(); } @@ -27,8 +27,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleDelete(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + context.Response.StatusCode = 418; + context.Response.StatusDescription = "I'm a teapot"; context.Response.End(); } @@ -38,8 +38,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleGet(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + context.Response.StatusCode = 418; + context.Response.StatusDescription = "I'm a teapot"; context.Response.End(); } @@ -49,8 +49,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleHead(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + context.Response.StatusCode = 418; + context.Response.StatusDescription = "I'm a teapot"; context.Response.End(); } @@ -60,8 +60,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleOptions(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + context.Response.StatusCode = 418; + context.Response.StatusDescription = "I'm a teapot"; context.Response.End(); } @@ -71,8 +71,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandlePatch(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + context.Response.StatusCode = 418; + context.Response.StatusDescription = "I'm a teapot"; context.Response.End(); } @@ -82,8 +82,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandlePost(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + context.Response.StatusCode = 418; + context.Response.StatusDescription = "I'm a teapot"; context.Response.End(); } @@ -93,8 +93,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandlePut(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + context.Response.StatusCode = 418; + context.Response.StatusDescription = "I'm a teapot"; context.Response.End(); } @@ -104,8 +104,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleTrace(HttpCwsContext context) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; + context.Response.StatusCode = 418; + context.Response.StatusDescription = "I'm a teapot"; context.Response.End(); } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs index d4cdac38..300b36f7 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs @@ -10,8 +10,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { private const string Key = "DevJsonRequestHandler"; private const uint Trace = 0; - private const uint Info = 0; - private const uint Verbose = 0; + private const uint Info = 1; + private const uint Verbose = 2; /// /// Handles CONNECT method requests diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs index faa0fff3..a10e66fb 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs @@ -10,8 +10,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { private const string Key = "DevListRequestHandler"; private const uint Trace = 0; - private const uint Info = 0; - private const uint Verbose = 0; + private const uint Info = 1; + private const uint Verbose = 2; /// /// Handles CONNECT method requests diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs index 34ab4f77..9f254ec5 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs @@ -11,8 +11,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { private const string Key = "DevPropsRequestHandler"; private const uint Trace = 0; - private const uint Info = 0; - private const uint Verbose = 0; + private const uint Info = 1; + private const uint Verbose = 2; /// /// Handles CONNECT method requests diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs index 8cfc7315..cec258be 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs @@ -5,6 +5,11 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DisableAllStreamDebugRequestHandler : WebApiBaseRequestHandler { + private const string Key = "DisableAllStreamDebugRequestHandler"; + private const uint Trace = 0; + private const uint Info = 1; + private const uint Verbose = 2; + /// /// Handles CONNECT method requests /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs index 0421266f..766cda57 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs @@ -10,8 +10,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { private const string Key = "GetJoinMapForBridgeKeyRequestHandler"; private const uint Trace = 0; - private const uint Info = 0; - private const uint Verbose = 0; + private const uint Info = 1; + private const uint Verbose = 2; /// /// Handles CONNECT method requests diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs index 863e3d29..fd7a11dd 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs @@ -11,8 +11,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { private const string Key = "GetJoinMapForDeviceKeyRequestHandler"; private const uint Trace = 0; - private const uint Info = 0; - private const uint Verbose = 0; + private const uint Info = 1; + private const uint Verbose = 2; /// /// Handles CONNECT method requests diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs index 42cf84c0..ee839c06 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs @@ -1,8 +1,9 @@ -using Crestron.SimplSharp.WebScripting; +using System; +using System.Linq; +using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; -using PepperDash.Essentials.Core.Bridges; namespace PepperDash.Essentials.Core.Web.RequestHandlers { @@ -10,8 +11,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { private const string Key = "GetTypesByFilterRequestHandler"; private const uint Trace = 0; - private const uint Info = 0; - private const uint Verbose = 0; + private const uint Info = 1; + private const uint Verbose = 2; /// /// Handles CONNECT method requests @@ -51,10 +52,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var routeDataJson = JsonConvert.SerializeObject(routeData, Formatting.Indented); - Debug.Console(Verbose, "routeData:\n{0}", routeDataJson); - + Debug.Console(Verbose, "[{0}] routeData:\n{1}", Key.ToLower(), routeDataJson); object filterObj; if (!routeData.Values.TryGetValue("filter", out filterObj)) @@ -68,11 +67,15 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var types = DeviceFactory.GetDeviceFactoryDictionary(filterObj.ToString()); + var types = DeviceFactory.GetDeviceFactoryDictionary(filterObj.ToString()).Select(type => new + { + Type = type.Key, + Description = type.Value.Description, + CType = type.Value.CType == null ? "---" : type.Value.CType.ToString() + }).Cast().ToList(); + if (types == null) { - Debug.Console(Verbose, "Get device type from dictionary failed"); - context.Response.StatusCode = 400; context.Response.StatusDescription = "Bad Request"; context.Response.End(); @@ -80,22 +83,28 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var js = JsonConvert.SerializeObject(types, Formatting.Indented, new JsonSerializerSettings + try { - ReferenceLoopHandling = ReferenceLoopHandling.Ignore, - NullValueHandling = NullValueHandling.Ignore, - MissingMemberHandling = MissingMemberHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore, - TypeNameHandling = TypeNameHandling.None - }); - Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); + var js = JsonConvert.SerializeObject(types, Formatting.Indented); + //Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); - context.Response.StatusCode = 200; - context.Response.StatusDescription = "OK"; - context.Response.ContentType = "application/json"; - context.Response.ContentEncoding = System.Text.Encoding.UTF8; - context.Response.Write(js, false); - context.Response.End(); + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = System.Text.Encoding.UTF8; + context.Response.Write(js, false); + context.Response.End(); + } + catch (Exception ex) + { + Debug.Console(Info, "[{0}] HandleGet Exception Message: {1}", Key.ToLower(), ex.Message); + Debug.Console(Verbose, "[{0}] HandleGet Exception StackTrace: {1}", Key.ToLower(), ex.StackTrace); + if (ex.InnerException != null) Debug.Console(Verbose, "[{0}] HandleGet Exception InnerException: {1}", Key.ToLower(), ex.InnerException); + + context.Response.StatusCode = 500; + context.Response.StatusDescription = "Internal Server Error"; + context.Response.End(); + } } /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs index bd1b967a..16f1f6b0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs @@ -1,4 +1,6 @@ -using System.Linq; +using System; +using System.Collections.Generic; +using System.Linq; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; using PepperDash.Core; @@ -10,8 +12,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { private const string Key = "GetTypesRequestHandler"; private const uint Trace = 0; - private const uint Info = 0; - private const uint Verbose = 0; + private const uint Info = 1; + private const uint Verbose = 2; /// /// Handles CONNECT method requests @@ -41,13 +43,9 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleGet(HttpCwsContext context) { - // TODO [ ] DeviceFactory.FactoryMethods dictionary is private and the method GetDeviceFactoryTypes has a return type void - // added new public method to return the DeviceFactory.FactoryMethod dictionary - var types = DeviceFactory.GetDeviceFactoryDictionary(null); - if (types == null) + var routeData = context.Request.RouteData; + if (routeData == null) { - Debug.Console(Verbose, "Get device factory dictionary failed"); - context.Response.StatusCode = 400; context.Response.StatusDescription = "Bad Request"; context.Response.End(); @@ -55,24 +53,47 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - types.OrderBy(t => t.Key); + var routeDataJson = JsonConvert.SerializeObject(routeData, Formatting.Indented); + Debug.Console(Verbose, "[{0}] routeData:\n{1}", Key.ToLower(), routeDataJson); - var js = JsonConvert.SerializeObject(types, Formatting.Indented, new JsonSerializerSettings + var types = DeviceFactory.GetDeviceFactoryDictionary(string.Empty).Select(type => new { - ReferenceLoopHandling = ReferenceLoopHandling.Ignore, - NullValueHandling = NullValueHandling.Ignore, - MissingMemberHandling = MissingMemberHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore, - TypeNameHandling = TypeNameHandling.None - }); - //Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); + Type = type.Key, + Description = type.Value.Description, + CType = type.Value.CType == null ? "---" : type.Value.CType.ToString() + }).Cast().ToList(); - context.Response.StatusCode = 200; - context.Response.StatusDescription = "OK"; - context.Response.ContentType = "application/json"; - context.Response.ContentEncoding = System.Text.Encoding.UTF8; - context.Response.Write(js, false); - context.Response.End(); + if (types == null) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + try + { + var js = JsonConvert.SerializeObject(types, Formatting.Indented); + //Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = System.Text.Encoding.UTF8; + context.Response.Write(js, false); + context.Response.End(); + } + catch (Exception ex) + { + Debug.Console(Info, "[{0}] HandleGet Exception Message: {1}", Key.ToLower(), ex.Message); + Debug.Console(Verbose, "[{0}] HandleGet Exception StackTrace: {1}", Key.ToLower(), ex.StackTrace); + if (ex.InnerException != null) Debug.Console(Verbose, "[{0}] HandleGet Exception InnerException: {1}", Key.ToLower(), ex.InnerException); + + context.Response.StatusCode = 500; + context.Response.StatusDescription = "Internal Server Error"; + context.Response.End(); + } } /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs index ab0e4d8d..90960902 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs @@ -9,8 +9,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { private const string Key = "ReportVersionsRequestHandler"; private const uint Trace = 0; - private const uint Info = 0; - private const uint Verbose = 0; + private const uint Info = 1; + private const uint Verbose = 2; /// /// Handles CONNECT method requests diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs index 989cb663..0874db11 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs @@ -11,8 +11,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { private const string Key = "SetDeviceStreamDebugRequestHandler"; private const uint Trace = 0; - private const uint Info = 0; - private const uint Verbose = 0; + private const uint Info = 1; + private const uint Verbose = 2; /// /// Handles CONNECT method requests diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs index e8621e33..d3cbbe99 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs @@ -9,8 +9,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { private const string Key = "ShowConfigRequestHandler"; private const uint Trace = 0; - private const uint Info = 0; - private const uint Verbose = 0; + private const uint Info = 1; + private const uint Verbose = 2; /// /// Handles CONNECT method requests From 0793a0909525bfd87a3e93fef2b9c707fba96a5b Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 1 Feb 2023 11:15:13 -0600 Subject: [PATCH 190/202] feat: added static methods for GetJoinMaps, added GetFeedbacksForDevice request handler --- .../PepperDash_Essentials_Core.csproj | 2 + .../Web/EssemtialsWebApi.cs | 5 + .../GetFeedbacksForDeviceRequestHandler.cs | 191 ++++++++++++++++++ .../GetJoinMapForBridgeKeyRequestHandler.cs | 22 +- .../GetJoinMapForDeviceKeyRequestHandler.cs | 10 +- .../Web/RequestHandlers/GetJoinMapHelpers.cs | 37 ++++ 6 files changed, 246 insertions(+), 21 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapHelpers.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 4742a04f..361d64c9 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -198,6 +198,8 @@ + + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs index 149cc021..2299cfbd 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs @@ -147,6 +147,11 @@ namespace PepperDash.Essentials.Core.Web { Name = "GetJoinMapsForDeviceKey", RouteHandler = new GetJoinMapForDeviceKeyRequestHandler() + }, + new HttpCwsRoute("feedbacks/{deviceKey}") + { + Name = "GetFeedbacksForDeviceKey", + RouteHandler = new GetFeedbacksForDeviceRequestHandler() } }; diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs new file mode 100644 index 00000000..06c7b4af --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs @@ -0,0 +1,191 @@ +using System; +using System.Linq; +using System.Runtime.CompilerServices; +using Crestron.SimplSharp.WebScripting; +using Newtonsoft.Json; +using PepperDash.Core; +using PepperDash.Core.Web.RequestHandlers; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class GetFeedbacksForDeviceRequestHandler : WebApiBaseRequestHandler + { + private const string Key = "GetFeedbacksForDeviceRequestHandler"; + private const uint Trace = 0; + private const uint Info = 1; + private const uint Verbose = 2; + + /// + /// Handles CONNECT method requests + /// + /// + protected override void HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles DELETE method requests + /// + /// + protected override void HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + var routeData = context.Request.RouteData; + if (routeData == null) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + //var routeDataJson = JsonConvert.SerializeObject(routeData, Formatting.Indented); + //Debug.Console(Verbose, "[{0}] routeData:\n{1}", Key.ToLower(), routeDataJson); + + object deviceObj; + if (!routeData.Values.TryGetValue("deviceKey", out deviceObj)) + { + Debug.Console(Verbose, "TryGetValue filter failed"); + + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } + + + var device = DeviceManager.GetDeviceForKey(deviceObj.ToString()) as IHasFeedback; + if (device == null) + { + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Not Found"; + context.Response.End(); + + return; + } + + var boolFeedback = + from feedback in device.Feedbacks.OfType() + where !string.IsNullOrEmpty(feedback.Key) + select new + { + FeedbackKey = feedback.Key, + Value = feedback.BoolValue + }; + + var intFeedback = + from feedback in device.Feedbacks.OfType() + where !string.IsNullOrEmpty(feedback.Key) + select new + { + FeedbackKey = feedback.Key, + Value = feedback.IntValue + }; + + var stringFeedback = + from feedback in device.Feedbacks.OfType() + where !string.IsNullOrEmpty(feedback.Key) + select new + { + FeedbackKey = feedback.Key, + Value = feedback.StringValue ?? string.Empty + }; + + var respnse = new + { + BoolValues = boolFeedback, + IntValues = intFeedback, + SerialValues = stringFeedback + }; + + var final = JsonConvert.SerializeObject(respnse, Formatting.Indented); + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = System.Text.Encoding.UTF8; + context.Response.Write(final, false); + context.Response.End(); + } + + /// + /// Handles HEAD method requests + /// + /// + protected override void HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles OPTIONS method requests + /// + /// + protected override void HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PATCH method requests + /// + /// + protected override void HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles POST method requests + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles PUT method requests + /// + /// + protected override void HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Handles TRACE method requests + /// + /// + protected override void HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs index 766cda57..d7a5a0d3 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs @@ -1,4 +1,7 @@ -using Crestron.SimplSharp.WebScripting; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; @@ -51,10 +54,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var routeDataJson = JsonConvert.SerializeObject(routeData, Formatting.Indented); - Debug.Console(Verbose, "routeData:\n{0}", routeDataJson); - + //Debug.Console(Verbose, "routeData:\n{0}", routeDataJson); object bridgeObj; if (!routeData.Values.TryGetValue("bridgeKey", out bridgeObj)) @@ -78,7 +79,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var joinMap = bridge.JoinMaps; + var joinMap = bridge.JoinMaps.Select(j => GetJoinMapHelpers.MapJoinToObject(j)).ToList(); if (joinMap == null) { context.Response.StatusCode = 400; @@ -88,14 +89,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var js = JsonConvert.SerializeObject(joinMap, Formatting.Indented, new JsonSerializerSettings - { - ReferenceLoopHandling = ReferenceLoopHandling.Ignore, - NullValueHandling = NullValueHandling.Ignore, - MissingMemberHandling = MissingMemberHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore, - TypeNameHandling = TypeNameHandling.None - }); + var js = JsonConvert.SerializeObject(joinMap, Formatting.Indented); Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); context.Response.StatusCode = 200; @@ -171,5 +165,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.StatusDescription = "Not Implemented"; context.Response.End(); } + + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs index fd7a11dd..da12303d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; using PepperDash.Core; @@ -100,15 +101,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - - var joinMap = new Dictionary - { - { - deviceObj.ToString(), - deviceJoinMap - } - }; + var joinMap = GetJoinMapHelpers.MapJoinToObject(deviceObj.ToString(), deviceJoinMap); var js = JsonConvert.SerializeObject(joinMap, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapHelpers.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapHelpers.cs new file mode 100644 index 00000000..8789067c --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapHelpers.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using System.Linq; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class GetJoinMapHelpers + { + public static object MapJoinToObject(string key, JoinMapBaseAdvanced join) + { + var kp = new KeyValuePair(key, join); + + return MapJoinToObject(kp); + } + + public static object MapJoinToObject(KeyValuePair join) + { + return new + { + DeviceKey = join.Key, + Joins = join.Value.Joins.Select(j => MapJoinDatacompleteToObject(j)) + }; + } + + public static object MapJoinDatacompleteToObject(KeyValuePair joinData) + { + return new + { + Signal = joinData.Key, + Description = joinData.Value.Metadata.Description, + JoinNumber = joinData.Value.JoinNumber, + JoinSpan = joinData.Value.JoinSpan, + JoinType = joinData.Value.Metadata.JoinType.ToString(), + JoinCapabilities = joinData.Value.Metadata.JoinCapabilities.ToString() + }; + } + } +} \ No newline at end of file From 55a5cc53c990a2b37138ae4810d47b61e0b5b941 Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 1 Feb 2023 11:30:35 -0600 Subject: [PATCH 191/202] refactor: moved and renamed GetJoinHelper class to EssentialsWebApiHelpers, added func for loaded assemblies --- .../PepperDash_Essentials_Core.csproj | 2 +- ...pHelpers.cs => EssentialsWebApiHelpers.cs} | 13 ++++++++++-- .../RequestHandlers/AppDebugRequestHandler.cs | 20 ++++++------------- .../RequestHandlers/DefaultRequestHandler.cs | 5 ----- .../GetJoinMapForBridgeKeyRequestHandler.cs | 2 +- .../GetJoinMapForDeviceKeyRequestHandler.cs | 2 +- .../ReportVersionsRequestHandler.cs | 20 +++++++++---------- 7 files changed, 29 insertions(+), 35 deletions(-) rename essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/{RequestHandlers/GetJoinMapHelpers.cs => EssentialsWebApiHelpers.cs} (76%) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 361d64c9..9c4a73c5 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -199,7 +199,7 @@ - + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapHelpers.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs similarity index 76% rename from essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapHelpers.cs rename to essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs index 8789067c..e978657d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapHelpers.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs @@ -1,10 +1,19 @@ using System.Collections.Generic; using System.Linq; -namespace PepperDash.Essentials.Core.Web.RequestHandlers +namespace PepperDash.Essentials.Core.Web { - public class GetJoinMapHelpers + public class EssentialsWebApiHelpers { + public static object MapToAssemblyObject(LoadedAssembly assembly) + { + return new + { + Name = assembly.Name, + Version = assembly.Version + }; + } + public static object MapJoinToObject(string key, JoinMapBaseAdvanced join) { var kp = new KeyValuePair(key, join); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs index ad413b7f..134fbbf2 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs @@ -9,11 +9,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class AppDebugRequestHandler : WebApiBaseRequestHandler { - private const string Key = "AppDebugRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// @@ -42,10 +37,9 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleGet(HttpCwsContext context) { - var o = new AppDebug(); - o.Level = Debug.Level; + var appDebug = new AppDebug {Level = Debug.Level}; - var body = JsonConvert.SerializeObject(o, Formatting.Indented); + var body = JsonConvert.SerializeObject(appDebug, Formatting.Indented); context.Response.StatusCode = 200; context.Response.StatusDescription = "OK"; @@ -97,16 +91,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers var bytes = new Byte[context.Request.ContentLength]; context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); var data = Encoding.UTF8.GetString(bytes, 0, bytes.Length); - //Debug.Console(Info, "[{0}] Request data:\n{1}", Key.ToLower(), data); - var o = new AppDebug(); - var requestBody = JsonConvert.DeserializeAnonymousType(data, o); + var appDebug = new AppDebug(); + var requestBody = JsonConvert.DeserializeAnonymousType(data, appDebug); Debug.SetDebugLevel(requestBody.Level); - o.Level = Debug.Level; - - var responseBody = JsonConvert.SerializeObject(o, Formatting.Indented); + appDebug.Level = Debug.Level; + var responseBody = JsonConvert.SerializeObject(appDebug, Formatting.Indented); context.Response.StatusCode = 200; context.Response.StatusDescription = "OK"; diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DefaultRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DefaultRequestHandler.cs index 19bc8cb3..4ffa500a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DefaultRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DefaultRequestHandler.cs @@ -5,11 +5,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DefaultRequestHandler : WebApiBaseRequestHandler { - private const string Key = "DefaultRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs index d7a5a0d3..dfc6fcb8 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs @@ -79,7 +79,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var joinMap = bridge.JoinMaps.Select(j => GetJoinMapHelpers.MapJoinToObject(j)).ToList(); + var joinMap = bridge.JoinMaps.Select(j => EssentialsWebApiHelpers.MapJoinToObject(j)).ToList(); if (joinMap == null) { context.Response.StatusCode = 400; diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs index da12303d..a71f193c 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs @@ -102,7 +102,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var joinMap = GetJoinMapHelpers.MapJoinToObject(deviceObj.ToString(), deviceJoinMap); + var joinMap = EssentialsWebApiHelpers.MapJoinToObject(deviceObj.ToString(), deviceJoinMap); var js = JsonConvert.SerializeObject(joinMap, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs index 90960902..b12cba09 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs @@ -7,11 +7,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class ReportVersionsRequestHandler : WebApiBaseRequestHandler { - private const string Key = "ReportVersionsRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// @@ -40,11 +35,15 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleGet(HttpCwsContext context) { - var assemblies = PluginLoader.LoadedAssemblies.Select(assembly => new + var loadAssemblies = PluginLoader.LoadedAssemblies; + if (loadAssemblies == null) { - Name = assembly.Name, - Version = assembly.Version - }).Cast().ToList(); + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Not Found"; + context.Response.End(); + } + + var assemblies = loadAssemblies.Select(a => EssentialsWebApiHelpers.MapToAssemblyObject(a)).ToList(); var js = JsonConvert.SerializeObject(assemblies, Formatting.Indented, new JsonSerializerSettings { @@ -54,8 +53,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers DefaultValueHandling = DefaultValueHandling.Ignore, TypeNameHandling = TypeNameHandling.None }); - //Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); - + context.Response.StatusCode = 200; context.Response.StatusDescription = "OK"; context.Response.ContentType = "application/json"; From 8bb670c43b50bd47e93e91e81b34ce9d71c9a9c8 Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 1 Feb 2023 11:31:52 -0600 Subject: [PATCH 192/202] fix: changed response status to 500 if loaded assemblies is null --- .../Web/RequestHandlers/ReportVersionsRequestHandler.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs index b12cba09..117363c6 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs @@ -38,9 +38,11 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers var loadAssemblies = PluginLoader.LoadedAssemblies; if (loadAssemblies == null) { - context.Response.StatusCode = 404; - context.Response.StatusDescription = "Not Found"; + context.Response.StatusCode = 500; + context.Response.StatusDescription = "Internal Server Error"; context.Response.End(); + + return; } var assemblies = loadAssemblies.Select(a => EssentialsWebApiHelpers.MapToAssemblyObject(a)).ToList(); From 087e74b2075248c2a09b13489c9ae02bc3ee80e0 Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 1 Feb 2023 11:32:19 -0600 Subject: [PATCH 193/202] fix: removed json serial settings --- .../Web/RequestHandlers/ReportVersionsRequestHandler.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs index 117363c6..6ba3cb7a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ReportVersionsRequestHandler.cs @@ -47,14 +47,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers var assemblies = loadAssemblies.Select(a => EssentialsWebApiHelpers.MapToAssemblyObject(a)).ToList(); - var js = JsonConvert.SerializeObject(assemblies, Formatting.Indented, new JsonSerializerSettings - { - ReferenceLoopHandling = ReferenceLoopHandling.Ignore, - NullValueHandling = NullValueHandling.Ignore, - MissingMemberHandling = MissingMemberHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore, - TypeNameHandling = TypeNameHandling.None - }); + var js = JsonConvert.SerializeObject(assemblies, Formatting.Indented); context.Response.StatusCode = 200; context.Response.StatusDescription = "OK"; From faaa2a354eb53c7f06a01d6d120dad7599b08fe1 Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 1 Feb 2023 11:34:36 -0600 Subject: [PATCH 194/202] refactor: removed debug statements, added 400 return if request content length is < 0 --- .../RequestHandlers/DevJsonRequestHandler.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs index 300b36f7..36bfd7f6 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs @@ -8,11 +8,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DevJsonRequestHandler : WebApiBaseRequestHandler { - private const string Key = "DevJsonRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// @@ -85,12 +80,20 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandlePost(HttpCwsContext context) { - if (context.Request.ContentLength < 0) return; + if (context.Request.ContentLength < 0) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } var bytes = new Byte[context.Request.ContentLength]; context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); var data = Encoding.UTF8.GetString(bytes, 0, bytes.Length); - Debug.Console(Info, "[{0}] Request data:\n{1}", Key.ToLower(), data); + + //Debug.Console(0, "Request data:\n{0}", data); try { From 4dc6d5b5accc9155e020172d0c547e7bad890a66 Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 1 Feb 2023 11:50:26 -0600 Subject: [PATCH 195/202] refactor: devlist request handler, added static method for creating list --- .../Web/EssentialsWebApiHelpers.cs | 18 +++++++++-- .../RequestHandlers/DevListRequestHandler.cs | 31 +++++++------------ 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs index e978657d..7186c9ec 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using PepperDash.Core; namespace PepperDash.Essentials.Core.Web { @@ -14,23 +15,34 @@ namespace PepperDash.Essentials.Core.Web }; } + public static object MapToDeviceListObject(IKeyed device) + { + return new + { + Key = device.Key, + Name = (device is IKeyName) + ? (device as IKeyName).Name + : "---" + }; + } + public static object MapJoinToObject(string key, JoinMapBaseAdvanced join) { var kp = new KeyValuePair(key, join); return MapJoinToObject(kp); } - + public static object MapJoinToObject(KeyValuePair join) { return new { DeviceKey = join.Key, - Joins = join.Value.Joins.Select(j => MapJoinDatacompleteToObject(j)) + Joins = join.Value.Joins.Select(j => MapJoinDataCompleteToObject(j)) }; } - public static object MapJoinDatacompleteToObject(KeyValuePair joinData) + public static object MapJoinDataCompleteToObject(KeyValuePair joinData) { return new { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs index a10e66fb..0c57ded0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs @@ -8,11 +8,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DevListRequestHandler : WebApiBaseRequestHandler { - private const string Key = "DevListRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// @@ -42,24 +37,20 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers protected override void HandleGet(HttpCwsContext context) { var allDevices = DeviceManager.AllDevices; + if (allDevices == null) + { + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Not Found"; + context.Response.End(); + + return; + } + allDevices.Sort((a, b) => System.String.Compare(a.Key, b.Key, System.StringComparison.Ordinal)); - var devices = allDevices.Select(device => new - { - Key = device.Key, - Name = device is IKeyName ? (device as IKeyName).Name : "---" + var deviceList = allDevices.Select(d => EssentialsWebApiHelpers.MapToDeviceListObject(d)).ToList(); - }).Cast().ToList(); - - var js = JsonConvert.SerializeObject(devices, Formatting.Indented, new JsonSerializerSettings - { - ReferenceLoopHandling = ReferenceLoopHandling.Ignore, - NullValueHandling = NullValueHandling.Ignore, - MissingMemberHandling = MissingMemberHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore, - TypeNameHandling = TypeNameHandling.None - }); - //Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); + var js = JsonConvert.SerializeObject(deviceList, Formatting.Indented); context.Response.StatusCode = 200; context.Response.StatusDescription = "OK"; From 12f3f519ccef5caf2327422a0825fa856c2de2eb Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 1 Feb 2023 11:58:22 -0600 Subject: [PATCH 196/202] refactor: cleaned up devprops handler --- .../RequestHandlers/DevPropsRequestHandler.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs index 9f254ec5..1a2e9157 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs @@ -9,11 +9,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DevPropsRequestHandler : WebApiBaseRequestHandler { - private const string Key = "DevPropsRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// @@ -91,15 +86,12 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers var bytes = new Byte[context.Request.ContentLength]; context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); var data = Encoding.UTF8.GetString(bytes, 0, bytes.Length); - //Debug.Console(Info, "[{0}] Request data:\n{1}", Key.ToLower(), data); var o = new DeviceActionWrapper(); var body = JsonConvert.DeserializeAnonymousType(data, o); if (string.IsNullOrEmpty(body.DeviceKey)) { - Debug.Console(Info, "[{0}] Request body is null or empty", Key.ToLower()); - context.Response.StatusCode = 400; context.Response.StatusDescription = "Bad Request"; context.Response.End(); @@ -108,6 +100,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers } var deviceProps = DeviceJsonApi.GetProperties(body.DeviceKey); + if (deviceProps == null || deviceProps.ToLower().Contains("no device")) + { + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Not Found"; + context.Response.End(); + + return; + } context.Response.StatusCode = 200; context.Response.StatusDescription = "OK"; From 1c1eabcef682e802b81c1d86a6c1caa6f4b6117f Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 1 Feb 2023 12:02:05 -0600 Subject: [PATCH 197/202] refactor: cleaned up unused using statements --- .../RequestHandlers/DevJsonRequestHandler.cs | 1 - .../RequestHandlers/DevListRequestHandler.cs | 1 - .../RequestHandlers/DevPropsRequestHandler.cs | 1 - .../DisableAllStreamDebugRequestHandler.cs | 5 ---- .../GetFeedbacksForDeviceRequestHandler.cs | 15 +--------- .../GetJoinMapForBridgeKeyRequestHandler.cs | 20 ++----------- .../GetJoinMapForDeviceKeyRequestHandler.cs | 30 ++++--------------- .../RequestHandlers/GetTypesRequestHandler.cs | 1 - 8 files changed, 10 insertions(+), 64 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs index 36bfd7f6..7806095e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs @@ -1,7 +1,6 @@ using System; using System.Text; using Crestron.SimplSharp.WebScripting; -using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs index 0c57ded0..c34542e2 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevListRequestHandler.cs @@ -1,7 +1,6 @@ using System.Linq; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; -using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs index 1a2e9157..c9f89c46 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs @@ -2,7 +2,6 @@ using System.Text; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; -using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs index cec258be..8cfc7315 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs @@ -5,11 +5,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DisableAllStreamDebugRequestHandler : WebApiBaseRequestHandler { - private const string Key = "DisableAllStreamDebugRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs index 06c7b4af..7e5c7be2 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs @@ -1,20 +1,12 @@ -using System; -using System.Linq; -using System.Runtime.CompilerServices; +using System.Linq; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; -using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class GetFeedbacksForDeviceRequestHandler : WebApiBaseRequestHandler { - private const string Key = "GetFeedbacksForDeviceRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// @@ -53,14 +45,9 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - //var routeDataJson = JsonConvert.SerializeObject(routeData, Formatting.Indented); - //Debug.Console(Verbose, "[{0}] routeData:\n{1}", Key.ToLower(), routeDataJson); - object deviceObj; if (!routeData.Values.TryGetValue("deviceKey", out deviceObj)) { - Debug.Console(Verbose, "TryGetValue filter failed"); - context.Response.StatusCode = 400; context.Response.StatusDescription = "Bad Request"; context.Response.End(); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs index dfc6fcb8..d037b9e6 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs @@ -1,9 +1,6 @@ -using System.Collections; -using System.Collections.Generic; -using System.Linq; +using System.Linq; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; -using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; using PepperDash.Essentials.Core.Bridges; @@ -11,11 +8,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class GetJoinMapForBridgeKeyRequestHandler : WebApiBaseRequestHandler { - private const string Key = "GetJoinMapForBridgeKeyRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// @@ -54,14 +46,9 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var routeDataJson = JsonConvert.SerializeObject(routeData, Formatting.Indented); - //Debug.Console(Verbose, "routeData:\n{0}", routeDataJson); - object bridgeObj; if (!routeData.Values.TryGetValue("bridgeKey", out bridgeObj)) { - Debug.Console(Verbose, "TryGetValue bridgeKey failed"); - context.Response.StatusCode = 400; context.Response.StatusDescription = "Bad Request"; context.Response.End(); @@ -82,15 +69,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers var joinMap = bridge.JoinMaps.Select(j => EssentialsWebApiHelpers.MapJoinToObject(j)).ToList(); if (joinMap == null) { - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Not Found"; context.Response.End(); return; } var js = JsonConvert.SerializeObject(joinMap, Formatting.Indented); - Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); context.Response.StatusCode = 200; context.Response.StatusDescription = "OK"; diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs index a71f193c..63ca47a0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs @@ -1,8 +1,5 @@ -using System.Collections.Generic; -using System.Linq; -using Crestron.SimplSharp.WebScripting; +using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; -using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; using PepperDash.Essentials.Core.Bridges; @@ -10,11 +7,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class GetJoinMapForDeviceKeyRequestHandler : WebApiBaseRequestHandler { - private const string Key = "GetJoinMapForDeviceKeyRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// @@ -53,16 +45,9 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - - var routeDataJson = JsonConvert.SerializeObject(routeData, Formatting.Indented); - Debug.Console(Verbose, "routeData:\n{0}", routeDataJson); - - object bridgeObj; if (!routeData.Values.TryGetValue("bridgeKey", out bridgeObj)) { - Debug.Console(Verbose, "TryGetValue bridgeKey failed"); - context.Response.StatusCode = 400; context.Response.StatusDescription = "Bad Request"; context.Response.End(); @@ -73,8 +58,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers object deviceObj; if (!routeData.Values.TryGetValue("deviceKey", out deviceObj)) { - Debug.Console(Verbose, "TryGetValue deviceKey failed"); - context.Response.StatusCode = 400; context.Response.StatusDescription = "Bad Request"; context.Response.End(); @@ -85,8 +68,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers var bridge = DeviceManager.GetDeviceForKey(bridgeObj.ToString()) as EiscApiAdvanced; if (bridge == null) { - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Not Found"; context.Response.End(); return; @@ -95,8 +78,8 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers JoinMapBaseAdvanced deviceJoinMap; if (!bridge.JoinMaps.TryGetValue(deviceObj.ToString(), out deviceJoinMap)) { - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; + context.Response.StatusCode = 500; + context.Response.StatusDescription = "Internal Server Error"; context.Response.End(); return; @@ -111,8 +94,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers DefaultValueHandling = DefaultValueHandling.Ignore, TypeNameHandling = TypeNameHandling.None }); - Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); - + context.Response.StatusCode = 200; context.Response.StatusDescription = "OK"; context.Response.ContentType = "application/json"; diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs index 16f1f6b0..d83660f7 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; From a3346d5ef4a93f3bf78feebe7ace855213569c74 Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 1 Feb 2023 12:22:52 -0600 Subject: [PATCH 198/202] refactor: added 400 bad request responses --- .../Web/EssentialsWebApiHelpers.cs | 17 ++++++ .../RequestHandlers/AppDebugRequestHandler.cs | 9 ++- .../RequestHandlers/DevPropsRequestHandler.cs | 9 ++- .../GetTypesByFilterRequestHandler.cs | 57 +++++-------------- .../RequestHandlers/GetTypesRequestHandler.cs | 55 +++++------------- .../SetDeviceStreamDebugRequestHandler.cs | 18 +++--- .../ShowConfigRequestHandler.cs | 5 -- 7 files changed, 68 insertions(+), 102 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs index 7186c9ec..37a749f9 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs @@ -54,5 +54,22 @@ namespace PepperDash.Essentials.Core.Web JoinCapabilities = joinData.Value.Metadata.JoinCapabilities.ToString() }; } + + public static object MapDeviceTypeToObject(string key, DeviceFactoryWrapper device) + { + var kp = new KeyValuePair(key, device); + + return MapDeviceTypeToObject(kp); + } + + public static object MapDeviceTypeToObject(KeyValuePair device) + { + return new + { + Type = device.Key, + Description = device.Value.Description, + CType = device.Value.CType == null ? "---": device.Value.CType.ToString() + }; + } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs index 134fbbf2..4d6ff236 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs @@ -86,7 +86,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandlePost(HttpCwsContext context) { - if (context.Request.ContentLength < 0) return; + if (context.Request.ContentLength < 0) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } var bytes = new Byte[context.Request.ContentLength]; context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs index c9f89c46..4ff70aad 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs @@ -80,7 +80,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandlePost(HttpCwsContext context) { - if (context.Request.ContentLength < 0) return; + if (context.Request.ContentLength < 0) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } var bytes = new Byte[context.Request.ContentLength]; context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs index ee839c06..be7347fb 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs @@ -1,19 +1,12 @@ -using System; -using System.Linq; +using System.Linq; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; -using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class GetTypesByFilterRequestHandler : WebApiBaseRequestHandler { - private const string Key = "GetTypesByFilterRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// @@ -52,14 +45,9 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var routeDataJson = JsonConvert.SerializeObject(routeData, Formatting.Indented); - Debug.Console(Verbose, "[{0}] routeData:\n{1}", Key.ToLower(), routeDataJson); - object filterObj; if (!routeData.Values.TryGetValue("filter", out filterObj)) { - Debug.Console(Verbose, "TryGetValue filter failed"); - context.Response.StatusCode = 400; context.Response.StatusDescription = "Bad Request"; context.Response.End(); @@ -67,44 +55,25 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var types = DeviceFactory.GetDeviceFactoryDictionary(filterObj.ToString()).Select(type => new + var deviceFactory = DeviceFactory.GetDeviceFactoryDictionary(filterObj.ToString()); + if (deviceFactory == null) { - Type = type.Key, - Description = type.Value.Description, - CType = type.Value.CType == null ? "---" : type.Value.CType.ToString() - }).Cast().ToList(); - - if (types == null) - { - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Not Found"; context.Response.End(); return; } - try - { - var js = JsonConvert.SerializeObject(types, Formatting.Indented); - //Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); + var deviceTypes = deviceFactory.Select(t => EssentialsWebApiHelpers.MapDeviceTypeToObject(t)).ToList(); + var js = JsonConvert.SerializeObject(deviceTypes, Formatting.Indented); - context.Response.StatusCode = 200; - context.Response.StatusDescription = "OK"; - context.Response.ContentType = "application/json"; - context.Response.ContentEncoding = System.Text.Encoding.UTF8; - context.Response.Write(js, false); - context.Response.End(); - } - catch (Exception ex) - { - Debug.Console(Info, "[{0}] HandleGet Exception Message: {1}", Key.ToLower(), ex.Message); - Debug.Console(Verbose, "[{0}] HandleGet Exception StackTrace: {1}", Key.ToLower(), ex.StackTrace); - if (ex.InnerException != null) Debug.Console(Verbose, "[{0}] HandleGet Exception InnerException: {1}", Key.ToLower(), ex.InnerException); - - context.Response.StatusCode = 500; - context.Response.StatusDescription = "Internal Server Error"; - context.Response.End(); - } + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = System.Text.Encoding.UTF8; + context.Response.Write(js, false); + context.Response.End(); } /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs index d83660f7..f2630063 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetTypesRequestHandler.cs @@ -1,19 +1,12 @@ -using System; -using System.Linq; +using System.Linq; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; -using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class GetTypesRequestHandler : WebApiBaseRequestHandler { - private const string Key = "GetTypesRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// @@ -52,47 +45,25 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var routeDataJson = JsonConvert.SerializeObject(routeData, Formatting.Indented); - Debug.Console(Verbose, "[{0}] routeData:\n{1}", Key.ToLower(), routeDataJson); - - var types = DeviceFactory.GetDeviceFactoryDictionary(string.Empty).Select(type => new + var deviceFactory = DeviceFactory.GetDeviceFactoryDictionary(null); + if (deviceFactory == null) { - Type = type.Key, - Description = type.Value.Description, - CType = type.Value.CType == null ? "---" : type.Value.CType.ToString() - }).Cast().ToList(); - - if (types == null) - { - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Not Found"; context.Response.End(); return; } - try - { - var js = JsonConvert.SerializeObject(types, Formatting.Indented); - //Debug.Console(Verbose, "[{0}] HandleGet: \x0d\x0a{1}", Key.ToLower(), js); + var deviceTypes = deviceFactory.Select(t => EssentialsWebApiHelpers.MapDeviceTypeToObject(t)).ToList(); + var js = JsonConvert.SerializeObject(deviceTypes, Formatting.Indented); - context.Response.StatusCode = 200; - context.Response.StatusDescription = "OK"; - context.Response.ContentType = "application/json"; - context.Response.ContentEncoding = System.Text.Encoding.UTF8; - context.Response.Write(js, false); - context.Response.End(); - } - catch (Exception ex) - { - Debug.Console(Info, "[{0}] HandleGet Exception Message: {1}", Key.ToLower(), ex.Message); - Debug.Console(Verbose, "[{0}] HandleGet Exception StackTrace: {1}", Key.ToLower(), ex.StackTrace); - if (ex.InnerException != null) Debug.Console(Verbose, "[{0}] HandleGet Exception InnerException: {1}", Key.ToLower(), ex.InnerException); - - context.Response.StatusCode = 500; - context.Response.StatusDescription = "Internal Server Error"; - context.Response.End(); - } + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = System.Text.Encoding.UTF8; + context.Response.Write(js, false); + context.Response.End(); } /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs index 0874db11..3625fcdd 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs @@ -2,18 +2,12 @@ using System.Text; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; -using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class SetDeviceStreamDebugRequestHandler : WebApiBaseRequestHandler { - private const string Key = "SetDeviceStreamDebugRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// @@ -86,13 +80,19 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandlePost(HttpCwsContext context) { - if (context.Request.ContentLength < 0) return; + if (context.Request.ContentLength < 0) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } var bytes = new Byte[context.Request.ContentLength]; context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); var data = Encoding.UTF8.GetString(bytes, 0, bytes.Length); - Debug.Console(Info, "[{0}] Request data:\n{1}", Key.ToLower(), data); - + var o = new { DeviceKey = "", diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs index d3cbbe99..4dded8b5 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/ShowConfigRequestHandler.cs @@ -7,11 +7,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class ShowConfigRequestHandler : WebApiBaseRequestHandler { - private const string Key = "ShowConfigRequestHandler"; - private const uint Trace = 0; - private const uint Info = 1; - private const uint Verbose = 2; - /// /// Handles CONNECT method requests /// From e1d7374f1eb1184b8feca405cd0eae23014db098 Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 1 Feb 2023 13:22:12 -0600 Subject: [PATCH 199/202] fix: resolved issues with setDeviceStreamDebug; refactor: added static method GetRequestBody --- .../Web/EssentialsWebApiHelpers.cs | 14 ++- .../RequestHandlers/AppDebugRequestHandler.cs | 12 +- .../RequestHandlers/DevJsonRequestHandler.cs | 14 ++- .../RequestHandlers/DevPropsRequestHandler.cs | 12 +- .../GetFeedbacksForDeviceRequestHandler.cs | 7 +- .../SetDeviceStreamDebugRequestHandler.cs | 105 ++++++++++++++---- 6 files changed, 129 insertions(+), 35 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs index 37a749f9..4830edb4 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssentialsWebApiHelpers.cs @@ -1,11 +1,23 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; +using System.Text; +using Crestron.SimplSharp.WebScripting; using PepperDash.Core; namespace PepperDash.Essentials.Core.Web { public class EssentialsWebApiHelpers { + public static string GetRequestBody(HttpCwsRequest request) + { + var bytes = new Byte[request.ContentLength]; + + request.InputStream.Read(bytes, 0, request.ContentLength); + + return Encoding.UTF8.GetString(bytes, 0, bytes.Length); + } + public static object MapToAssemblyObject(LoadedAssembly assembly) { return new diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs index 4d6ff236..f80f9f7f 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/AppDebugRequestHandler.cs @@ -95,9 +95,15 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var bytes = new Byte[context.Request.ContentLength]; - context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); - var data = Encoding.UTF8.GetString(bytes, 0, bytes.Length); + var data = EssentialsWebApiHelpers.GetRequestBody(context.Request); + if (string.IsNullOrEmpty(data)) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } var appDebug = new AppDebug(); var requestBody = JsonConvert.DeserializeAnonymousType(data, appDebug); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs index 7806095e..6080465b 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevJsonRequestHandler.cs @@ -88,12 +88,16 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var bytes = new Byte[context.Request.ContentLength]; - context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); - var data = Encoding.UTF8.GetString(bytes, 0, bytes.Length); - - //Debug.Console(0, "Request data:\n{0}", data); + var data = EssentialsWebApiHelpers.GetRequestBody(context.Request); + if (string.IsNullOrEmpty(data)) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + return; + } + try { DeviceJsonApi.DoDeviceActionWithJson(data); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs index 4ff70aad..b7dcc511 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/DevPropsRequestHandler.cs @@ -89,9 +89,15 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var bytes = new Byte[context.Request.ContentLength]; - context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); - var data = Encoding.UTF8.GetString(bytes, 0, bytes.Length); + var data = EssentialsWebApiHelpers.GetRequestBody(context.Request); + if (string.IsNullOrEmpty(data)) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; + } var o = new DeviceActionWrapper(); var body = JsonConvert.DeserializeAnonymousType(data, o); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs index 7e5c7be2..2f892f2b 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs @@ -93,19 +93,20 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers Value = feedback.StringValue ?? string.Empty }; - var respnse = new + var responseObj = new { BoolValues = boolFeedback, IntValues = intFeedback, SerialValues = stringFeedback }; - var final = JsonConvert.SerializeObject(respnse, Formatting.Indented); + var js = JsonConvert.SerializeObject(responseObj, Formatting.Indented); + context.Response.StatusCode = 200; context.Response.StatusDescription = "OK"; context.Response.ContentType = "application/json"; context.Response.ContentEncoding = System.Text.Encoding.UTF8; - context.Response.Write(final, false); + context.Response.Write(js, false); context.Response.End(); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs index 3625fcdd..bb7cc12f 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs @@ -1,7 +1,7 @@ using System; -using System.Text; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; +using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers @@ -89,24 +89,28 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - var bytes = new Byte[context.Request.ContentLength]; - context.Request.InputStream.Read(bytes, 0, context.Request.ContentLength); - var data = Encoding.UTF8.GetString(bytes, 0, bytes.Length); - - var o = new + var data = EssentialsWebApiHelpers.GetRequestBody(context.Request); + if (data == null) { - DeviceKey = "", - Type = "", - Timeout = 15 - }; + context.Response.StatusCode = 500; + context.Response.StatusDescription = "Internal Server Error"; + context.Response.End(); - var body = JsonConvert.DeserializeAnonymousType(data, o); + return; + } - if (string.IsNullOrEmpty(body.DeviceKey) || string.IsNullOrEmpty(body.Type) - || !body.Type.ToLower().Contains("off") - || !body.Type.ToLower().Contains("tx") - || !body.Type.ToLower().Contains("rx") - || !body.Type.ToLower().Contains("both")) + var config = new SetDeviceStreamDebugConfig(); + var body = JsonConvert.DeserializeAnonymousType(data, config); + if (body == null) + { + context.Response.StatusCode = 500; + context.Response.StatusDescription = "Internal Server Error"; + context.Response.End(); + + return; + } + + if (string.IsNullOrEmpty(body.DeviceKey) || string.IsNullOrEmpty(body.Setting)) { context.Response.StatusCode = 400; context.Response.StatusDescription = "Bad Request"; @@ -115,11 +119,52 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - DeviceManager.SetDeviceStreamDebugging(string.Format("setdevicestreamdebug {0} {1} {2}", body.DeviceKey, body.Type, body.Timeout)); + var device = DeviceManager.GetDeviceForKey(body.DeviceKey) as IStreamDebugging; + if (device == null) + { + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Not Found"; + context.Response.End(); - context.Response.StatusCode = 200; - context.Response.StatusDescription = "OK"; - context.Response.End(); + return; + } + + eStreamDebuggingSetting debugSetting; + try + { + debugSetting = (eStreamDebuggingSetting) Enum.Parse(typeof (eStreamDebuggingSetting), body.Setting, true); + } + catch (Exception ex) + { + context.Response.StatusCode = 500; + context.Response.StatusDescription = "Internal Server Error"; + context.Response.End(); + + return; + } + + try + { + var mins = Convert.ToUInt32(body.Timeout); + if (mins > 0) + { + device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, mins); + } + else + { + device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting); + } + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.End(); + } + catch (Exception ex) + { + context.Response.StatusCode = 500; + context.Response.StatusDescription = "Internal Server Error"; + context.Response.End(); + } } /// @@ -144,4 +189,24 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.End(); } } + + + public class SetDeviceStreamDebugConfig + { + [JsonProperty("deviceKey", NullValueHandling = NullValueHandling.Include)] + public string DeviceKey { get; set; } + + [JsonProperty("setting", NullValueHandling = NullValueHandling.Include)] + public string Setting { get; set; } + + [JsonProperty("timeout")] + public int Timeout { get; set; } + + public SetDeviceStreamDebugConfig() + { + DeviceKey = null; + Setting = null; + Timeout = 15; + } + } } \ No newline at end of file From 34d3b705fa323999a8074ad54e734a010acebaf3 Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 1 Feb 2023 15:30:21 -0600 Subject: [PATCH 200/202] fix: aded GetPaths method call when running on a server --- .../PepperDashEssentialsBase/Web/EssemtialsWebApi.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs index 2299cfbd..973b303b 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Web/EssemtialsWebApi.cs @@ -198,6 +198,8 @@ namespace PepperDash.Essentials.Core.Web Debug.Console(DebugTrace, Debug.ErrorLogLevel.Notice, "Starting Essentials Web API on Virtual Control Server"); _server.Start(); + + GetPaths(); } /// @@ -218,7 +220,7 @@ namespace PepperDash.Essentials.Core.Web CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0); var path = CrestronEnvironment.DevicePlatform == eDevicePlatform.Server - ? string.Format("http(s)://{0}/virtualcontrol/rooms/{1}/cws{2}", hostname, InitialParametersClass.RoomId, BasePath) + ? string.Format("http(s)://{0}/VirtualControl/Rooms/{1}/cws{2}", hostname, InitialParametersClass.RoomId, BasePath) : string.Format("http(s)://{0}/cws{1}", currentIp, BasePath); Debug.Console(DebugTrace, this, "Server:{0}", path); From cbec2f211925a2da2ee487bc1afa7c8f24307f40 Mon Sep 17 00:00:00 2001 From: jdevito Date: Thu, 2 Feb 2023 12:31:11 -0600 Subject: [PATCH 201/202] fix: updates to resolve directory issues updateDirectoryXsig logic to resolve showing contacts in root when folders are in use (ZoomRooms). LinkVideoCodecDirectoryToApi to resolve analog value driving total number of contacts when folders are in use (ZoomRooms). ConvertZoomContactsToGeneric to reference roomFolder.FolderId and contactFolder.FolderId in foreach loops. --- .../VideoCodec/VideoCodecBase.cs | 71 +++++++++++-------- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 12 +++- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 19c61b9f..c0048a68 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1004,7 +1004,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (codec.DirectoryRoot != null) { - trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)codec.DirectoryRoot.CurrentDirectoryResults.Count); + var contactsCount = codec.DirectoryRoot.CurrentDirectoryResults.Where(c => c.ParentFolderId.Equals("root")).ToList().Count; + trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)contactsCount); + Debug.Console(2, this, ">>> contactsCount: {0}", contactsCount); var clearBytes = XSigHelpers.ClearOutputs(); @@ -1020,7 +1022,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec codec.DirectoryResultReturned += (sender, args) => { - trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)args.Directory.CurrentDirectoryResults.Count); + var isRoot = codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false; + var argsCount = isRoot + ? args.Directory.CurrentDirectoryResults.Where(a => a.ParentFolderId.Equals("root")).ToList().Count + : args.Directory.CurrentDirectoryResults.Count; + + trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)argsCount); + Debug.Console(2, this, ">>> argsCount: {0}", argsCount); var clearBytes = XSigHelpers.ClearOutputs(); @@ -1184,46 +1192,47 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec return GetXSigString(tokenArray); } - private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot) - { - var xSigMaxIndex = 1023; - var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count > xSigMaxIndex - ? xSigMaxIndex - : directory.CurrentDirectoryResults.Count]; + private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot) + { + var xSigMaxIndex = 1023; + var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count > xSigMaxIndex + ? xSigMaxIndex + : directory.CurrentDirectoryResults.Count]; - Debug.Console(2, this, "IsRoot: {0}, Directory Count: {1}, TokenArray.Length: {2}", isRoot, - directory.CurrentDirectoryResults.Count, tokenArray.Length); + Debug.Console(2, this, "IsRoot: {0}, Directory Count: {1}, TokenArray.Length: {2}", isRoot, directory.CurrentDirectoryResults.Count, tokenArray.Length); - var contacts = directory.CurrentDirectoryResults.Count > xSigMaxIndex - ? directory.CurrentDirectoryResults.Take(xSigMaxIndex) - : directory.CurrentDirectoryResults; + var contacts = directory.CurrentDirectoryResults.Count > xSigMaxIndex + ? directory.CurrentDirectoryResults.Take(xSigMaxIndex) + : directory.CurrentDirectoryResults; - var counterIndex = 1; - foreach (var entry in contacts) - { - var arrayIndex = counterIndex - 1; - var entryIndex = counterIndex; + var contactsToDisplay = isRoot + ? contacts.Where(c => c.ParentFolderId == "root") + : contacts.Where(c => c.ParentFolderId != "root"); - Debug.Console(2, this, "Entry{2:0000} Name: {0}, Folder ID: {1}", entry.Name, entry.FolderId, entryIndex); + var counterIndex = 1; + foreach (var entry in contactsToDisplay) + { + var arrayIndex = counterIndex - 1; + var entryIndex = counterIndex; - if (entry is DirectoryFolder && entry.ParentFolderId == "root") - { - tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, String.Format("[+] {0}", entry.Name)); + 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); - counterIndex++; - counterIndex++; + if (entry is DirectoryFolder) + { + tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, String.Format("[+] {0}", entry.Name)); - continue; - } + counterIndex++; - tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, entry.Name); + continue; + } - counterIndex++; - } - - return GetXSigString(tokenArray); + tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, entry.Name); + counterIndex++; + } + return GetXSigString(tokenArray); } private void LinkVideoCodecCallControlsToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index 0075b657..79a5395d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -303,11 +303,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { var contact = new InvitableDirectoryContact { Name = c.ScreenName, ContactId = c.Jid }; - contact.ContactMethods.Add(new ContactMethod() { Number = c.Jid, Device = eContactMethodDevice.Video, CallType = eContactMethodCallType.Video, ContactMethodId = c.Jid }); + contact.ContactMethods.Add(new ContactMethod() + { + Number = c.Jid, + Device = eContactMethodDevice.Video, + CallType = eContactMethodCallType.Video, + ContactMethodId = c.Jid + }); if (folders.Count > 0) { - contact.ParentFolderId = c.IsZoomRoom ? "rooms" : "contacts"; + contact.ParentFolderId = c.IsZoomRoom + ? roomFolder.FolderId // "rooms" + : contactFolder.FolderId; // "contacts" } contacts.Add(contact); From e05186defdf01ae4f6ea417e62e3b75ce7398c86 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 7 Feb 2023 09:33:46 -0700 Subject: [PATCH 202/202] chore: update packages to use 1.1.5-beta-317 --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index 87f5b8c1..ea9f8e18 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file