From a43101585397e282c251ddd67d551c92cf95e849 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 12 Nov 2020 11:16:43 -0700 Subject: [PATCH 01/17] Adds legacy typename to factory for CiscoSparkCodec --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 2 +- 1 file changed, 1 insertion(+), 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 429794bc..e2a094dc 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 @@ -2102,7 +2102,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { public CiscoSparkCodecFactory() { - TypeNames = new List() { "ciscospark", "ciscowebex", "ciscowebexpro", "ciscoroomkit" }; + TypeNames = new List() { "ciscospark", "ciscowebex", "ciscowebexpro", "ciscoroomkit", "ciscosparkpluscodec" }; } public override EssentialsDevice BuildDevice(DeviceConfig dc) From af0e2180bd20aa5866c680c5bafbcfd9945bef1e Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 12 Nov 2020 11:44:11 -0700 Subject: [PATCH 02/17] Adds back in a factory and necessary methods to build a GenericVersiportInputDevice --- .../Inputs/GenericDigitalInputDevice.cs | 108 ++++++++--------- .../Inputs/GenericVersiportInputDevice.cs | 112 +++++++++++++++++- 2 files changed, 163 insertions(+), 57 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericDigitalInputDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericDigitalInputDevice.cs index e57e869d..23b261c0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericDigitalInputDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericDigitalInputDevice.cs @@ -1,32 +1,32 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DeviceSupport; -using Newtonsoft.Json; -using PepperDash.Core; -using PepperDash.Essentials.Core.Bridges; -using PepperDash.Essentials.Core.Config; - - -namespace PepperDash.Essentials.Core.CrestronIO +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using Newtonsoft.Json; +using PepperDash.Core; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Config; + + +namespace PepperDash.Essentials.Core.CrestronIO { [Description("Wrapper class for Digital Input")] - public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput - { - public DigitalInput InputPort { get; private set; } - - public BoolFeedback InputStateFeedback { get; private set; } - - Func InputStateFeedbackFunc - { - get - { - return () => InputPort.State; - } - } + public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput + { + public DigitalInput InputPort { get; private set; } + + public BoolFeedback InputStateFeedback { get; private set; } + + Func InputStateFeedbackFunc + { + get + { + return () => InputPort.State; + } + } public GenericDigitalInputDevice(string key, string name, Func postActivationFunc, @@ -40,15 +40,15 @@ namespace PepperDash.Essentials.Core.CrestronIO InputPort.Register(); - InputPort.StateChange += InputPort_StateChange; + InputPort.StateChange += InputPort_StateChange; }); } #region Events - void InputPort_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args) - { + void InputPort_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args) + { InputStateFeedback.FireUpdate(); } @@ -81,7 +81,7 @@ namespace PepperDash.Essentials.Core.CrestronIO } if (ioPortDevice == null) { - Debug.Console(0, "GetDigitalInput: Device '0' is not a valid IRelayPorts Device", dc.PortDeviceKey); + Debug.Console(0, "GetDigitalInput: Device '0' is not a valid IDigitalInputPorts Device", dc.PortDeviceKey); return null; } @@ -99,13 +99,13 @@ namespace PepperDash.Essentials.Core.CrestronIO #region Bridge Linking - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { - var joinMap = new IDigitalInputJoinMap(joinStart); - - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - - if (!string.IsNullOrEmpty(joinMapSerialized)) + var joinMap = new IDigitalInputJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) joinMap = JsonConvert.DeserializeObject(joinMapSerialized); if (bridge != null) @@ -115,19 +115,19 @@ namespace PepperDash.Essentials.Core.CrestronIO else { Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } - - try - { - Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - - // Link feedback for input state - InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]); - } - catch (Exception e) - { - Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key); - Debug.Console(1, this, "Error: {0}", e); + } + + try + { + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + // Link feedback for input state + InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]); + } + catch (Exception e) + { + Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key); + Debug.Console(1, this, "Error: {0}", e); } } @@ -144,7 +144,7 @@ namespace PepperDash.Essentials.Core.CrestronIO public override EssentialsDevice BuildDevice(DeviceConfig dc) { - Debug.Console(1, "Factory Attempting to create new Generic Relay Device"); + Debug.Console(1, "Factory Attempting to create new Generic Digital Input Device"); var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); @@ -158,7 +158,7 @@ namespace PepperDash.Essentials.Core.CrestronIO #endregion - } - - + } + + } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs index 90ff4fa0..be9ad367 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs @@ -4,15 +4,21 @@ using System.Linq; using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; +using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Core.Bridges; + + +using Newtonsoft.Json; namespace PepperDash.Essentials.Core.CrestronIO { /// /// Represents a generic digital input deviced tied to a versiport /// - public class GenericVersiportDigitalInputDevice : EssentialsDevice, IDigitalInput + public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput { public Versiport InputPort { get; private set; } @@ -26,8 +32,8 @@ namespace PepperDash.Essentials.Core.CrestronIO } } - public GenericVersiportDigitalInputDevice(string key, Versiport inputPort, IOPortConfig props): - base(key) + public GenericVersiportDigitalInputDevice(string key, string name, Versiport inputPort, IOPortConfig props): + base(key, name) { InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc); InputPort = inputPort; @@ -46,5 +52,105 @@ namespace PepperDash.Essentials.Core.CrestronIO if(args.Event == eVersiportEvent.DigitalInChange) InputStateFeedback.FireUpdate(); } + + + #region Bridge Linking + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new IDigitalInputJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } + + try + { + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + // Link feedback for input state + InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]); + } + catch (Exception e) + { + Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key); + Debug.Console(1, this, "Error: {0}", e); + } + } + + #endregion + + + public static Versiport GetVersiportDigitalInput(IOPortConfig dc) + { + + IIOPorts ioPortDevice; + + if (dc.PortDeviceKey.Equals("processor")) + { + if (!Global.ControlSystem.SupportsDigitalInput) + { + Debug.Console(0, "GetVersiportDigitalInput: Processor does not support Versiports"); + return null; + } + ioPortDevice = Global.ControlSystem; + } + else + { + var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts; + if (ioPortDev == null) + { + Debug.Console(0, "GetVersiportDigitalInput: Device {0} is not a valid device", dc.PortDeviceKey); + return null; + } + ioPortDevice = ioPortDev; + } + if (ioPortDevice == null) + { + Debug.Console(0, "GetVersiportDigitalInput: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey); + return null; + } + + if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts) + { + Debug.Console(0, "GetVersiportDigitalInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); + } + + return ioPortDevice.VersiPorts[dc.PortNumber]; + + + } + } + + + public class GenericVersiportDigitalInputDeviceFactory : EssentialsDeviceFactory + { + public GenericVersiportDigitalInputDeviceFactory() + { + TypeNames = new List() { "versiportinput" }; + } + + 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 GenericVersiportDigitalInputDevice(dc.Key, dc.Name, GenericVersiportDigitalInputDevice.GetVersiportDigitalInput(props), props); + + return portDevice; + } } } \ No newline at end of file From 73addfefe74d3a6c0aa9d7ad6c70311b917ebdbe Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 12 Nov 2020 12:11:18 -0700 Subject: [PATCH 03/17] More fixes to Generic IO classes --- .../Inputs/GenericDigitalInputDevice.cs | 1 + .../Inputs/GenericVersiportInputDevice.cs | 30 ++- .../Crestron IO/Relay/GenericRelayDevice.cs | 230 +++++++++--------- 3 files changed, 137 insertions(+), 124 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericDigitalInputDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericDigitalInputDevice.cs index 23b261c0..db905bfa 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericDigitalInputDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericDigitalInputDevice.cs @@ -33,6 +33,7 @@ namespace PepperDash.Essentials.Core.CrestronIO IOPortConfig config) : base(key, name) { + InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc); AddPostActivationAction(() => { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs index be9ad367..f9c854b7 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs @@ -32,17 +32,29 @@ namespace PepperDash.Essentials.Core.CrestronIO } } - public GenericVersiportDigitalInputDevice(string key, string name, Versiport inputPort, IOPortConfig props): + public GenericVersiportDigitalInputDevice(string key, string name, Func postActivationFunc, IOPortConfig config) : base(key, name) { InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc); - InputPort = inputPort; - InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput); - if (props.DisablePullUpResistor) - InputPort.DisablePullUpResistor = true; - InputPort.VersiportChange += new VersiportEventHandler(InputPort_VersiportChange); - Debug.Console(1, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", props.PortNumber, InputPort.DisablePullUpResistor); + AddPostActivationAction(() => + { + InputPort = postActivationFunc(config); + + InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput); + if (config.DisablePullUpResistor) + InputPort.DisablePullUpResistor = true; + + InputPort.Register(); + + InputPort.VersiportChange += InputPort_VersiportChange; + + + + Debug.Console(1, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor); + + }); + } void InputPort_VersiportChange(Versiport port, VersiportEventArgs args) @@ -98,7 +110,7 @@ namespace PepperDash.Essentials.Core.CrestronIO if (dc.PortDeviceKey.Equals("processor")) { - if (!Global.ControlSystem.SupportsDigitalInput) + if (!Global.ControlSystem.SupportsVersiport) { Debug.Console(0, "GetVersiportDigitalInput: Processor does not support Versiports"); return null; @@ -148,7 +160,7 @@ namespace PepperDash.Essentials.Core.CrestronIO if (props == null) return null; - var portDevice = new GenericVersiportDigitalInputDevice(dc.Key, dc.Name, GenericVersiportDigitalInputDevice.GetVersiportDigitalInput(props), props); + var portDevice = new GenericVersiportDigitalInputDevice(dc.Key, dc.Name, GenericVersiportDigitalInputDevice.GetVersiportDigitalInput, props); return portDevice; } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/GenericRelayDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/GenericRelayDevice.cs index 050ac23b..445ac338 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/GenericRelayDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/GenericRelayDevice.cs @@ -1,25 +1,25 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DeviceSupport; -using Newtonsoft.Json; -using PepperDash.Core; -using PepperDash.Essentials.Core.Bridges; -using PepperDash.Essentials.Core.Config; - -namespace PepperDash.Essentials.Core.CrestronIO -{ - /// - /// Represents a generic device controlled by relays +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using Newtonsoft.Json; +using PepperDash.Core; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Config; + +namespace PepperDash.Essentials.Core.CrestronIO +{ + /// + /// Represents a generic device controlled by relays /// [Description("Wrapper class for a Relay")] - public class GenericRelayDevice : EssentialsBridgeableDevice, ISwitchedOutput - { - public Relay RelayOutput { get; private set; } - + public class GenericRelayDevice : EssentialsBridgeableDevice, ISwitchedOutput + { + public Relay RelayOutput { get; private set; } + public BoolFeedback OutputIsOnFeedback { get; private set; } //Maintained for compatibility with PepperDash.Essentials.Core.Devices.CrestronProcessor @@ -94,11 +94,11 @@ namespace PepperDash.Essentials.Core.CrestronIO #region Events - void RelayOutput_StateChange(Relay relay, RelayEventArgs args) - { + void RelayOutput_StateChange(Relay relay, RelayEventArgs args) + { OutputIsOnFeedback.FireUpdate(); - } - + } + #endregion #region Methods @@ -119,33 +119,33 @@ namespace PepperDash.Essentials.Core.CrestronIO OpenRelay(); else CloseRelay(); - } + } #endregion - - #region ISwitchedOutput Members - - void ISwitchedOutput.On() - { - CloseRelay(); - } - - void ISwitchedOutput.Off() - { - OpenRelay(); - } - + + #region ISwitchedOutput Members + + void ISwitchedOutput.On() + { + CloseRelay(); + } + + void ISwitchedOutput.Off() + { + OpenRelay(); + } + #endregion #region Bridge Linking - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { - var joinMap = new GenericRelayControllerJoinMap(joinStart); - - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - - if (!string.IsNullOrEmpty(joinMapSerialized)) + var joinMap = new GenericRelayControllerJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) joinMap = JsonConvert.DeserializeObject(joinMapSerialized); if (bridge != null) @@ -155,26 +155,26 @@ namespace PepperDash.Essentials.Core.CrestronIO else { Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } - - if (RelayOutput == null) - { - Debug.Console(1, this, "Unable to link device '{0}'. Relay is null", Key); - return; - } - - Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - - trilist.SetBoolSigAction(joinMap.Relay.JoinNumber, b => - { - if (b) - CloseRelay(); - else - OpenRelay(); - }); - - // feedback for relay state - + } + + if (RelayOutput == null) + { + Debug.Console(1, this, "Unable to link device '{0}'. Relay is null", Key); + return; + } + + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + trilist.SetBoolSigAction(joinMap.Relay.JoinNumber, b => + { + if (b) + CloseRelay(); + else + OpenRelay(); + }); + + // feedback for relay state + OutputIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Relay.JoinNumber]); } @@ -202,54 +202,54 @@ namespace PepperDash.Essentials.Core.CrestronIO return portDevice; - /* - if (props.PortDeviceKey == "processor") - portDevice = Global.ControlSystem as IRelayPorts; - else - portDevice = DeviceManager.GetDeviceForKey(props.PortDeviceKey) as IRelayPorts; - - if (portDevice == null) - Debug.Console(0, "Unable to add relay device with key '{0}'. Port Device does not support relays", key); - else - { - var cs = (portDevice as CrestronControlSystem); - - if (cs != null) - { - // The relay is on a control system processor - if (!cs.SupportsRelay || props.PortNumber > cs.NumberOfRelayPorts) - { - Debug.Console(0, "Port Device: {0} does not support relays or does not have enough relays"); - return null; - } - } - else - { - // The relay is on another device type - - if (props.PortNumber > portDevice.NumberOfRelayPorts) - { - Debug.Console(0, "Port Device: {0} does not have enough relays"); - return null; - } - } - - Relay relay = portDevice.RelayPorts[props.PortNumber]; - - if (!relay.Registered) - { - if (relay.Register() == eDeviceRegistrationUnRegistrationResponse.Success) - return new GenericRelayDevice(key, relay); - else - Debug.Console(0, "Attempt to register relay {0} on device with key '{1}' failed.", props.PortNumber, props.PortDeviceKey); - } - else - { - return new GenericRelayDevice(key, relay); - } - - // Future: Check if portDevice is 3-series card or other non control system that supports versiports - } + /* + if (props.PortDeviceKey == "processor") + portDevice = Global.ControlSystem as IRelayPorts; + else + portDevice = DeviceManager.GetDeviceForKey(props.PortDeviceKey) as IRelayPorts; + + if (portDevice == null) + Debug.Console(0, "Unable to add relay device with key '{0}'. Port Device does not support relays", key); + else + { + var cs = (portDevice as CrestronControlSystem); + + if (cs != null) + { + // The relay is on a control system processor + if (!cs.SupportsRelay || props.PortNumber > cs.NumberOfRelayPorts) + { + Debug.Console(0, "Port Device: {0} does not support relays or does not have enough relays"); + return null; + } + } + else + { + // The relay is on another device type + + if (props.PortNumber > portDevice.NumberOfRelayPorts) + { + Debug.Console(0, "Port Device: {0} does not have enough relays"); + return null; + } + } + + Relay relay = portDevice.RelayPorts[props.PortNumber]; + + if (!relay.Registered) + { + if (relay.Register() == eDeviceRegistrationUnRegistrationResponse.Success) + return new GenericRelayDevice(key, relay); + else + Debug.Console(0, "Attempt to register relay {0} on device with key '{1}' failed.", props.PortNumber, props.PortDeviceKey); + } + else + { + return new GenericRelayDevice(key, relay); + } + + // Future: Check if portDevice is 3-series card or other non control system that supports versiports + } */ } @@ -258,7 +258,7 @@ namespace PepperDash.Essentials.Core.CrestronIO #endregion - } - - + } + + } \ No newline at end of file From 3d224496a8c63780983dce71d05342ba538c14e1 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 12 Nov 2020 12:33:04 -0700 Subject: [PATCH 04/17] Adds new event to DeviceManager to indicate that all devices have been activated. Necessary for MicrophonePrivacyManager #485 --- .../Inputs/GenericVersiportInputDevice.cs | 4 +- .../Devices/DeviceManager.cs | 847 +++++++++--------- .../MicrophonePrivacyController.cs | 6 +- 3 files changed, 437 insertions(+), 420 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs index f9c854b7..20acdd4d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs @@ -41,12 +41,12 @@ namespace PepperDash.Essentials.Core.CrestronIO { InputPort = postActivationFunc(config); + InputPort.Register(); + InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput); if (config.DisablePullUpResistor) InputPort.DisablePullUpResistor = true; - InputPort.Register(); - InputPort.VersiportChange += InputPort_VersiportChange; diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs index d50de428..0e4efa10 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs @@ -1,342 +1,355 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; - -using PepperDash.Core; - - -namespace PepperDash.Essentials.Core -{ - public static class DeviceManager - { - private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection(); - private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true); - //public static List Devices { get { return _Devices; } } - //static List _Devices = new List(); - - static readonly Dictionary Devices = new Dictionary(StringComparer.OrdinalIgnoreCase); - - /// - /// Returns a copy of all the devices in a list - /// - public static List AllDevices { get { return new List(Devices.Values); } } - - public static bool AddDeviceEnabled; - - public static void Initialize(CrestronControlSystem cs) - { - AddDeviceEnabled = true; - CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices", - ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks", - ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices", - ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "", - ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s)), "devprops", "", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s)), "devmethods", "", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive", - "Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator); - - CrestronConsole.AddNewConsoleCommand(s => SetDeviceStreamDebugging(s), "setdevicestreamdebug", "set comm debug [deviceKey] [off/rx/tx/both] ([minutes])", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => DisableAllDeviceStreamDebugging(), "disableallstreamdebug", "disables stream debugging on all devices", ConsoleAccessLevelEnum.AccessOperator); - } - - /// - /// Calls activate steps on all Device class items - /// - public static void ActivateAll() - { - try - { - DeviceCriticalSection.Enter(); - AddDeviceEnabled = false; - // PreActivate all devices - foreach (var d in Devices.Values) - { - try - { - if (d is Device) - (d as Device).PreActivate(); - } - catch (Exception e) - { - Debug.Console(0, d, "ERROR: Device PreActivation failure:\r{0}", e); - } - } - - // Activate all devices - foreach (var d in Devices.Values) - { - try - { - if (d is Device) - (d as Device).Activate(); - } - catch (Exception e) - { - Debug.Console(0, d, "ERROR: Device Activation failure:\r{0}", e); - } - } - - // PostActivate all devices - foreach (var d in Devices.Values) - { - try - { - if (d is Device) - (d as Device).PostActivate(); - } - catch (Exception e) - { - Debug.Console(0, d, "ERROR: Device PostActivation failure:\r{0}", e); - } - } - } - finally - { - DeviceCriticalSection.Leave(); - } - } - - /// - /// Calls activate on all Device class items - /// - public static void DeactivateAll() - { - try - { - DeviceCriticalSection.Enter(); - foreach (var d in Devices.Values.OfType()) - { - d.Deactivate(); - } - } - finally - { - DeviceCriticalSection.Leave(); - } - } - - //static void ListMethods(string devKey) - //{ - // var dev = GetDeviceForKey(devKey); - // if(dev != null) - // { - // var type = dev.GetType().GetCType(); - // var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance); - // var sb = new StringBuilder(); - // sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length)); - // foreach (var m in methods) - // { - // sb.Append(string.Format("{0}(", m.Name)); - // var pars = m.GetParameters(); - // foreach (var p in pars) - // sb.Append(string.Format("({1}){0} ", p.Name, p.ParameterType.Name)); - // sb.AppendLine(")"); - // } - // CrestronConsole.ConsoleCommandResponse(sb.ToString()); - // } - //} - - private static void ListDevices(string s) - { - Debug.Console(0, "{0} Devices registered with Device Manager:", Devices.Count); - var sorted = Devices.Values.ToList(); - sorted.Sort((a, b) => a.Key.CompareTo(b.Key)); - - foreach (var d in sorted) - { - var name = d is IKeyName ? (d as IKeyName).Name : "---"; - Debug.Console(0, " [{0}] {1}", d.Key, name); - } - } - - private static void ListDeviceFeedbacks(string devKey) - { - var dev = GetDeviceForKey(devKey); - if (dev == null) - { - Debug.Console(0, "Device '{0}' not found", devKey); - return; - } - var statusDev = dev as IHasFeedback; - if (statusDev == null) - { - Debug.Console(0, "Device '{0}' does not have visible feedbacks", devKey); - return; - } - statusDev.DumpFeedbacksToConsole(true); - } - - //static void ListDeviceCommands(string devKey) - //{ - // var dev = GetDeviceForKey(devKey); - // if (dev == null) - // { - // Debug.Console(0, "Device '{0}' not found", devKey); - // return; - // } - // Debug.Console(0, "This needs to be reworked. Stay tuned.", devKey); - //} - - private static void ListDeviceCommStatuses(string input) - { - var sb = new StringBuilder(); - foreach (var dev in Devices.Values.OfType()) - { - sb.Append(string.Format("{0}: {1}\r", dev, - dev.CommunicationMonitor.Status)); - } - CrestronConsole.ConsoleCommandResponse(sb.ToString()); - } - - - //static void DoDeviceCommand(string command) - //{ - // Debug.Console(0, "Not yet implemented. Stay tuned"); - //} - - public static void AddDevice(IKeyed newDev) - { - try - { - if (!DeviceCriticalSection.TryEnter()) - { - Debug.Console(0, Debug.ErrorLogLevel.Error, "Currently unable to add devices to Device Manager. Please try again"); - return; - } - // Check for device with same key - //var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase)); - ////// If it exists, remove or warn?? - //if (existingDevice != null) - - if (!AddDeviceEnabled) - { - Debug.Console(0, Debug.ErrorLogLevel.Error, "All devices have been activated. Adding new devices is not allowed."); - return; - } - - if (Devices.ContainsKey(newDev.Key)) - { - Debug.Console(0, newDev, "WARNING: A device with this key already exists. Not added to manager"); - return; - } - Devices.Add(newDev.Key, newDev); - //if (!(_Devices.Contains(newDev))) - // _Devices.Add(newDev); - } - finally - { - DeviceCriticalSection.Leave(); - } - } - - public static void AddDevice(IEnumerable devicesToAdd) - { - try - { - if (!DeviceCriticalSection.TryEnter()) - { - Debug.Console(0, Debug.ErrorLogLevel.Error, - "Currently unable to add devices to Device Manager. Please try again"); - return; - } - if (!AddDeviceEnabled) - { - Debug.Console(0, Debug.ErrorLogLevel.Error, - "All devices have been activated. Adding new devices is not allowed."); - return; - } - - foreach (var dev in devicesToAdd) - { - try - { - Devices.Add(dev.Key, dev); - } - catch (ArgumentException ex) - { - Debug.Console(0, "Error adding device with key {0} to Device Manager: {1}\r\nStack Trace: {2}", - dev.Key, ex.Message, ex.StackTrace); - } - } - } - finally - { - DeviceCriticalSection.Leave(); - } - } - - public static void RemoveDevice(IKeyed newDev) - { - try - { - DeviceCriticalSection.Enter(); - if (newDev == null) - return; - if (Devices.ContainsKey(newDev.Key)) - Devices.Remove(newDev.Key); - //if (_Devices.Contains(newDev)) - // _Devices.Remove(newDev); - else - Debug.Console(0, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key); - } - finally - { - DeviceCriticalSection.Leave(); - } - } - - public static IEnumerable GetDeviceKeys() - { - //return _Devices.Select(d => d.Key).ToList(); - return Devices.Keys; - } - - public static IEnumerable GetDevices() - { - //return _Devices.Select(d => d.Key).ToList(); - return Devices.Values; - } - - public static IKeyed GetDeviceForKey(string key) - { - //return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); - if (key != null && Devices.ContainsKey(key)) - return Devices[key]; - - return null; - } - - /// - /// Console handler that simulates com port data receive - /// - /// - public static void SimulateComReceiveOnDevice(string s) - { - // devcomsim:1 xyzabc - var match = Regex.Match(s, @"(\S*)\s*(.*)"); - if (match.Groups.Count < 3) - { - CrestronConsole.ConsoleCommandResponse(" Format: devsimreceive:P "); - return; - } - //Debug.Console(2, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value); - - var com = GetDeviceForKey(match.Groups[1].Value) as ComPortController; - if (com == null) - { - CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value); - return; - } - com.SimulateReceive(match.Groups[2].Value); +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; + +using PepperDash.Core; + + +namespace PepperDash.Essentials.Core +{ + public static class DeviceManager + { + public static event EventHandler AllDevicesActivated; + + private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection(); + private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true); + //public static List Devices { get { return _Devices; } } + //static List _Devices = new List(); + + static readonly Dictionary Devices = new Dictionary(StringComparer.OrdinalIgnoreCase); + + /// + /// Returns a copy of all the devices in a list + /// + public static List AllDevices { get { return new List(Devices.Values); } } + + public static bool AddDeviceEnabled; + + public static void Initialize(CrestronControlSystem cs) + { + AddDeviceEnabled = true; + CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices", + ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks", + ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices", + ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "", + ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s)), "devprops", "", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s)), "devmethods", "", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive", + "Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator); + + CrestronConsole.AddNewConsoleCommand(s => SetDeviceStreamDebugging(s), "setdevicestreamdebug", "set comm debug [deviceKey] [off/rx/tx/both] ([minutes])", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => DisableAllDeviceStreamDebugging(), "disableallstreamdebug", "disables stream debugging on all devices", ConsoleAccessLevelEnum.AccessOperator); + } + + /// + /// Calls activate steps on all Device class items + /// + public static void ActivateAll() + { + try + { + DeviceCriticalSection.Enter(); + AddDeviceEnabled = false; + // PreActivate all devices + foreach (var d in Devices.Values) + { + try + { + if (d is Device) + (d as Device).PreActivate(); + } + catch (Exception e) + { + Debug.Console(0, d, "ERROR: Device PreActivation failure:\r{0}", e); + } + } + + // Activate all devices + foreach (var d in Devices.Values) + { + try + { + if (d is Device) + (d as Device).Activate(); + } + catch (Exception e) + { + Debug.Console(0, d, "ERROR: Device Activation failure:\r{0}", e); + } + } + + // PostActivate all devices + foreach (var d in Devices.Values) + { + try + { + if (d is Device) + (d as Device).PostActivate(); + } + catch (Exception e) + { + Debug.Console(0, d, "ERROR: Device PostActivation failure:\r{0}", e); + } + } + + OnAllDevicesActivated(); + } + finally + { + DeviceCriticalSection.Leave(); + } + } + + private static void OnAllDevicesActivated() + { + var handler = AllDevicesActivated; + if (handler != null) + { + handler(null, new EventArgs()); + } + } + + /// + /// Calls activate on all Device class items + /// + public static void DeactivateAll() + { + try + { + DeviceCriticalSection.Enter(); + foreach (var d in Devices.Values.OfType()) + { + d.Deactivate(); + } + } + finally + { + DeviceCriticalSection.Leave(); + } + } + + //static void ListMethods(string devKey) + //{ + // var dev = GetDeviceForKey(devKey); + // if(dev != null) + // { + // var type = dev.GetType().GetCType(); + // var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance); + // var sb = new StringBuilder(); + // sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length)); + // foreach (var m in methods) + // { + // sb.Append(string.Format("{0}(", m.Name)); + // var pars = m.GetParameters(); + // foreach (var p in pars) + // sb.Append(string.Format("({1}){0} ", p.Name, p.ParameterType.Name)); + // sb.AppendLine(")"); + // } + // CrestronConsole.ConsoleCommandResponse(sb.ToString()); + // } + //} + + private static void ListDevices(string s) + { + Debug.Console(0, "{0} Devices registered with Device Manager:", Devices.Count); + var sorted = Devices.Values.ToList(); + sorted.Sort((a, b) => a.Key.CompareTo(b.Key)); + + foreach (var d in sorted) + { + var name = d is IKeyName ? (d as IKeyName).Name : "---"; + Debug.Console(0, " [{0}] {1}", d.Key, name); + } + } + + private static void ListDeviceFeedbacks(string devKey) + { + var dev = GetDeviceForKey(devKey); + if (dev == null) + { + Debug.Console(0, "Device '{0}' not found", devKey); + return; + } + var statusDev = dev as IHasFeedback; + if (statusDev == null) + { + Debug.Console(0, "Device '{0}' does not have visible feedbacks", devKey); + return; + } + statusDev.DumpFeedbacksToConsole(true); + } + + //static void ListDeviceCommands(string devKey) + //{ + // var dev = GetDeviceForKey(devKey); + // if (dev == null) + // { + // Debug.Console(0, "Device '{0}' not found", devKey); + // return; + // } + // Debug.Console(0, "This needs to be reworked. Stay tuned.", devKey); + //} + + private static void ListDeviceCommStatuses(string input) + { + var sb = new StringBuilder(); + foreach (var dev in Devices.Values.OfType()) + { + sb.Append(string.Format("{0}: {1}\r", dev, + dev.CommunicationMonitor.Status)); + } + CrestronConsole.ConsoleCommandResponse(sb.ToString()); + } + + + //static void DoDeviceCommand(string command) + //{ + // Debug.Console(0, "Not yet implemented. Stay tuned"); + //} + + public static void AddDevice(IKeyed newDev) + { + try + { + if (!DeviceCriticalSection.TryEnter()) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Currently unable to add devices to Device Manager. Please try again"); + return; + } + // Check for device with same key + //var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase)); + ////// If it exists, remove or warn?? + //if (existingDevice != null) + + if (!AddDeviceEnabled) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "All devices have been activated. Adding new devices is not allowed."); + return; + } + + if (Devices.ContainsKey(newDev.Key)) + { + Debug.Console(0, newDev, "WARNING: A device with this key already exists. Not added to manager"); + return; + } + Devices.Add(newDev.Key, newDev); + //if (!(_Devices.Contains(newDev))) + // _Devices.Add(newDev); + } + finally + { + DeviceCriticalSection.Leave(); + } + } + + public static void AddDevice(IEnumerable devicesToAdd) + { + try + { + if (!DeviceCriticalSection.TryEnter()) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, + "Currently unable to add devices to Device Manager. Please try again"); + return; + } + if (!AddDeviceEnabled) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, + "All devices have been activated. Adding new devices is not allowed."); + return; + } + + foreach (var dev in devicesToAdd) + { + try + { + Devices.Add(dev.Key, dev); + } + catch (ArgumentException ex) + { + Debug.Console(0, "Error adding device with key {0} to Device Manager: {1}\r\nStack Trace: {2}", + dev.Key, ex.Message, ex.StackTrace); + } + } + } + finally + { + DeviceCriticalSection.Leave(); + } + } + + public static void RemoveDevice(IKeyed newDev) + { + try + { + DeviceCriticalSection.Enter(); + if (newDev == null) + return; + if (Devices.ContainsKey(newDev.Key)) + Devices.Remove(newDev.Key); + //if (_Devices.Contains(newDev)) + // _Devices.Remove(newDev); + else + Debug.Console(0, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key); + } + finally + { + DeviceCriticalSection.Leave(); + } + } + + public static IEnumerable GetDeviceKeys() + { + //return _Devices.Select(d => d.Key).ToList(); + return Devices.Keys; + } + + public static IEnumerable GetDevices() + { + //return _Devices.Select(d => d.Key).ToList(); + return Devices.Values; + } + + public static IKeyed GetDeviceForKey(string key) + { + //return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); + if (key != null && Devices.ContainsKey(key)) + return Devices[key]; + + return null; + } + + /// + /// Console handler that simulates com port data receive + /// + /// + public static void SimulateComReceiveOnDevice(string s) + { + // devcomsim:1 xyzabc + var match = Regex.Match(s, @"(\S*)\s*(.*)"); + if (match.Groups.Count < 3) + { + CrestronConsole.ConsoleCommandResponse(" Format: devsimreceive:P "); + return; + } + //Debug.Console(2, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value); + + var com = GetDeviceForKey(match.Groups[1].Value) as ComPortController; + if (com == null) + { + CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value); + return; + } + com.SimulateReceive(match.Groups[2].Value); } /// @@ -366,82 +379,82 @@ namespace PepperDash.Essentials.Core Debug.Console(0, "{0}", routingOutputPort.Key); } } - } - - /// - /// Attempts to set the debug level of a device - /// - /// - public static void SetDeviceStreamDebugging(string s) - { - var args = s.Split(' '); - - var deviceKey = args[0]; - var setting = args[1]; - - var timeout= String.Empty; - - if (args.Length >= 3) - { - timeout = args[2]; - } - - var device = GetDeviceForKey(deviceKey) as IStreamDebugging; - - if (device == null) - { - Debug.Console(0, "Unable to get device with key: {0}", deviceKey); - return; - } - - eStreamDebuggingSetting debugSetting; - - try - { - debugSetting = (eStreamDebuggingSetting)Enum.Parse(typeof(eStreamDebuggingSetting), setting, true); - } - catch - { - Debug.Console(0, "Unable to convert setting value. Please use off/rx/tx/both"); - return; - } - - if (!string.IsNullOrEmpty(timeout)) - { - try - { - var min = Convert.ToUInt32(timeout); - - device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, min); - Debug.Console(0, "Device: '{0}' debug level set to {1) for {2} minutes", deviceKey, debugSetting, min); - - } - catch (Exception e) - { - Debug.Console(0, "Unable to convert minutes or settings value. Please use an integer value for minutes. Errro: {0}", e); - } - } - else - { - device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting); - Debug.Console(0, "Device: '{0}' debug level set to {1) for default time (30 minutes)", deviceKey, debugSetting); - } - } - - /// - /// Sets stream debugging settings to off for all devices - /// - public static void DisableAllDeviceStreamDebugging() - { - foreach (var device in AllDevices) - { - var streamDevice = device as IStreamDebugging; - - if (streamDevice != null) - { - streamDevice.StreamDebugging.SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting.Off); - } - } - } - } + } + + /// + /// Attempts to set the debug level of a device + /// + /// + public static void SetDeviceStreamDebugging(string s) + { + var args = s.Split(' '); + + var deviceKey = args[0]; + var setting = args[1]; + + var timeout= String.Empty; + + if (args.Length >= 3) + { + timeout = args[2]; + } + + var device = GetDeviceForKey(deviceKey) as IStreamDebugging; + + if (device == null) + { + Debug.Console(0, "Unable to get device with key: {0}", deviceKey); + return; + } + + eStreamDebuggingSetting debugSetting; + + try + { + debugSetting = (eStreamDebuggingSetting)Enum.Parse(typeof(eStreamDebuggingSetting), setting, true); + } + catch + { + Debug.Console(0, "Unable to convert setting value. Please use off/rx/tx/both"); + return; + } + + if (!string.IsNullOrEmpty(timeout)) + { + try + { + var min = Convert.ToUInt32(timeout); + + device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, min); + Debug.Console(0, "Device: '{0}' debug level set to {1) for {2} minutes", deviceKey, debugSetting, min); + + } + catch (Exception e) + { + Debug.Console(0, "Unable to convert minutes or settings value. Please use an integer value for minutes. Errro: {0}", e); + } + } + else + { + device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting); + Debug.Console(0, "Device: '{0}' debug level set to {1) for default time (30 minutes)", deviceKey, debugSetting); + } + } + + /// + /// Sets stream debugging settings to off for all devices + /// + public static void DisableAllDeviceStreamDebugging() + { + foreach (var device in AllDevices) + { + var streamDevice = device as IStreamDebugging; + + if (streamDevice != null) + { + streamDevice.StreamDebugging.SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting.Off); + } + } + } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Microphone Privacy/MicrophonePrivacyController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Microphone Privacy/MicrophonePrivacyController.cs index ece2c65f..0f15a02d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Microphone Privacy/MicrophonePrivacyController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Microphone Privacy/MicrophonePrivacyController.cs @@ -88,8 +88,12 @@ namespace PepperDash.Essentials.Core.Privacy else Debug.Console(0, this, "Unable to add Red LED device"); + DeviceManager.AllDevicesActivated += (o, a) => + { + CheckPrivacyMode(); + }; + AddPostActivationAction(() => { - CheckPrivacyMode(); PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange; PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange; }); From 5c63a49071878c45136b317bdaba586d4bcf4440 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 12 Nov 2020 15:57:10 -0700 Subject: [PATCH 05/17] Updates IMobileControl interface. Adds VideoCodec.StopSharing() to EndShutdown() method in Vtc1 room --- .../Room/Types/EssentialsHuddleVtc1Room.cs | 2 + .../DeviceTypeInterfaces/IMobileControl.cs | 4 +- .../VideoCodec/CiscoCodec/xEvent.cs | 278 +++++++++--------- .../VideoCodec/VideoCodecBase.cs | 23 +- 4 files changed, 161 insertions(+), 146 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index ffc6a4db..0bc48703 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -383,6 +383,7 @@ namespace PepperDash.Essentials protected override void EndShutdown() { VideoCodec.EndAllCalls(); + VideoCodec.StopSharing(); SetDefaultLevels(); @@ -652,6 +653,7 @@ namespace PepperDash.Essentials dest.ReleaseRoute(); if (dest is IHasPowerControl) (dest as IHasPowerControl).PowerOff(); + } else { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs index 616d61b1..6f4ff344 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs @@ -12,7 +12,7 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces void LinkSystemMonitorToAppServer(); - + IMobileControl GetAppServer(); } /// @@ -26,6 +26,8 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces string QrCodeUrl { get; } + string QrCodeChecksum { get; } + string McServerUrl { get; } string RoomName { get; } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xEvent.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xEvent.cs index 23594ce2..171e7bd0 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xEvent.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xEvent.cs @@ -1,131 +1,131 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco -{ - /// - /// This class exists to capture serialized data sent back by a Cisco codec in JSON output mode - /// - public class CiscoCodecEvents - { - public class CauseValue - { - public string id { get; set; } - public string Value { get; set; } - } - - public class CauseType - { - public string id { get; set; } - public string Value { get; set; } - } - - public class CauseString - { - public string id { get; set; } - public string Value { get; set; } - } - - public class OrigCallDirection - { - public string id { get; set; } - public string Value { get; set; } - } - - public class RemoteURI - { - public string id { get; set; } - public string Value { get; set; } - } - - public class DisplayName - { - public string id { get; set; } - public string Value { get; set; } - } - - public class CallId - { - public string id { get; set; } - public string Value { get; set; } - } - - public class CauseCode - { - public string id { get; set; } - public string Value { get; set; } - } - - public class CauseOrigin - { - public string id { get; set; } - public string Value { get; set; } - } - - public class Protocol - { - public string id { get; set; } - public string Value { get; set; } - } - - public class Duration - { - public string id { get; set; } - public string Value { get; set; } - } - - public class CallType - { - public string id { get; set; } - public string Value { get; set; } - } - - public class CallRate - { - public string id { get; set; } - public string Value { get; set; } - } - - public class Encryption - { - public string id { get; set; } - public string Value { get; set; } - } - - public class RequestedURI - { - public string id { get; set; } - public string Value { get; set; } - } - - public class PeopleCountAverage - { - public string id { get; set; } - public string Value { get; set; } - } - - public class CallDisconnect - { - public string id { get; set; } - public CauseValue CauseValue { get; set; } - public CauseType CauseType { get; set; } - public CauseString CauseString { get; set; } - public OrigCallDirection OrigCallDirection { get; set; } - public RemoteURI RemoteURI { get; set; } - public DisplayName DisplayName { get; set; } - public CallId CallId { get; set; } - public CauseCode CauseCode { get; set; } - public CauseOrigin CauseOrigin { get; set; } - public Protocol Protocol { get; set; } - public Duration Duration { get; set; } - public CallType CallType { get; set; } - public CallRate CallRate { get; set; } - public Encryption Encryption { get; set; } - public RequestedURI RequestedURI { get; set; } - public PeopleCountAverage PeopleCountAverage { get; set; } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco +{ + /// + /// This class exists to capture serialized data sent back by a Cisco codec in JSON output mode + /// + public class CiscoCodecEvents + { + public class CauseValue + { + public string id { get; set; } + public string Value { get; set; } + } + + public class CauseType + { + public string id { get; set; } + public string Value { get; set; } + } + + public class CauseString + { + public string id { get; set; } + public string Value { get; set; } + } + + public class OrigCallDirection + { + public string id { get; set; } + public string Value { get; set; } + } + + public class RemoteURI + { + public string id { get; set; } + public string Value { get; set; } + } + + public class DisplayName + { + public string id { get; set; } + public string Value { get; set; } + } + + public class CallId + { + public string id { get; set; } + public string Value { get; set; } + } + + public class CauseCode + { + public string id { get; set; } + public string Value { get; set; } + } + + public class CauseOrigin + { + public string id { get; set; } + public string Value { get; set; } + } + + public class Protocol + { + public string id { get; set; } + public string Value { get; set; } + } + + public class Duration + { + public string id { get; set; } + public string Value { get; set; } + } + + public class CallType + { + public string id { get; set; } + public string Value { get; set; } + } + + public class CallRate + { + public string id { get; set; } + public string Value { get; set; } + } + + public class Encryption + { + public string id { get; set; } + public string Value { get; set; } + } + + public class RequestedURI + { + public string id { get; set; } + public string Value { get; set; } + } + + public class PeopleCountAverage + { + public string id { get; set; } + public string Value { get; set; } + } + + public class CallDisconnect + { + public string id { get; set; } + public CauseValue CauseValue { get; set; } + public CauseType CauseType { get; set; } + public CauseString CauseString { get; set; } + public OrigCallDirection OrigCallDirection { get; set; } + public RemoteURI RemoteURI { get; set; } + public DisplayName DisplayName { get; set; } + public CallId CallId { get; set; } + public CauseCode CauseCode { get; set; } + public CauseOrigin CauseOrigin { get; set; } + public Protocol Protocol { get; set; } + public Duration Duration { get; set; } + public CallType CallType { get; set; } + public CallRate CallRate { get; set; } + public Encryption Encryption { get; set; } + public RequestedURI RequestedURI { get; set; } + public PeopleCountAverage PeopleCountAverage { get; set; } } public class UserInterface { @@ -151,16 +151,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { public string id { get; set; } public string Value { get; set; } - } - public class Event - { + } + public class Event + { public CallDisconnect CallDisconnect { get; set; } - public UserInterface UserInterface { get; set; } - } - - public class RootObject - { - public Event Event { get; set; } - } - } + public UserInterface UserInterface { get; set; } + } + + public class RootObject + { + public Event Event { get; set; } + } + } } \ 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 5af3c655..0977dea2 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 @@ -5,6 +5,7 @@ using System.Text; using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharp.Ssh; using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharp; using PepperDash.Core; using PepperDash.Core.Intersystem; using PepperDash.Core.Intersystem.Tokens; @@ -231,12 +232,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// protected void SetIsReady() { - IsReady = true; - var h = IsReadyChange; - if (h != null) - { - h(this, new EventArgs()); - } + CrestronInvoke.BeginInvoke( (o) => + { + try + { + IsReady = true; + var h = IsReadyChange; + if (h != null) + { + h(this, new EventArgs()); + } + } + catch (Exception e) + { + Debug.Console(2, this, "Error in SetIsReady() : {0}", e); + } + }); } // **** DEBUGGING THINGS **** From f9ba562b0b1c78586db5129a0268326a2ec00813 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 12 Nov 2020 16:23:14 -0700 Subject: [PATCH 06/17] Updates to work when there are multiple tie lines from codec inputs to sources and using ExternalSourceSwitching --- .../Room/Types/EssentialsHuddleVtc1Room.cs | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index 0bc48703..a462ffca 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -705,37 +705,44 @@ namespace PepperDash.Essentials } - /// - /// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch - /// - private void SetCodecExternalSources() - { - var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching; + /// + /// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch + /// + private void SetCodecExternalSources() + { + var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching; - if (videoCodecWithExternalSwitching == null) - { - return; - } + if (videoCodecWithExternalSwitching == null || !videoCodecWithExternalSwitching.ExternalSourceListEnabled) + { + return; + } - string codecTieLine = ConfigReader.ConfigObject.TieLines.SingleOrDefault(x => x.DestinationKey == VideoCodec.Key).DestinationPort; - videoCodecWithExternalSwitching.ClearExternalSources(); - videoCodecWithExternalSwitching.RunRouteAction = RunRouteAction; - var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ; + try + { + // Get the tie line that the external switcher is connected to + string codecInputConnectorName = ConfigReader.ConfigObject.TieLines.SingleOrDefault( + x => x.DestinationKey == VideoCodec.Key && x.DestinationPort == videoCodecWithExternalSwitching.ExternalSourceInputPort).DestinationPort; - foreach (var kvp in srcList) - { - var srcConfig = kvp.Value; + videoCodecWithExternalSwitching.ClearExternalSources(); + videoCodecWithExternalSwitching.RunRouteAction = RunRouteAction; + var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ; - if (kvp.Key != DefaultCodecRouteString && kvp.Key != "roomOff") - { + foreach (var kvp in srcList) + { + var srcConfig = kvp.Value; - videoCodecWithExternalSwitching.AddExternalSource(codecTieLine, kvp.Key, srcConfig.PreferredName, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceType.desktop); - videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready); - - - } - } - } + if (kvp.Key != DefaultCodecRouteString && kvp.Key != "roomOff") + { + videoCodecWithExternalSwitching.AddExternalSource(codecInputConnectorName, kvp.Key, srcConfig.PreferredName, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceType.desktop); + videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready); + } + } + } + catch (Exception e) + { + Debug.Console(2, this, "Error setting codec external sources: {0}", e); + } + } private void SetCodecBranding() { From 48585469f6e6aee14c0474b28b94cfa402ccbee8 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 12 Nov 2020 16:28:43 -0700 Subject: [PATCH 07/17] Additional updates to resolve external switching with multiple upstream tie lines --- .../Codec/IHasExternalSourceSwitching.cs | 1 + .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 9 ++++++++- .../CiscoCodec/CiscoSparkCodecPropertiesConfig.cs | 9 +++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasExternalSourceSwitching.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasExternalSourceSwitching.cs index b4449d86..f8ef33ee 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasExternalSourceSwitching.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasExternalSourceSwitching.cs @@ -11,6 +11,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec public interface IHasExternalSourceSwitching { bool ExternalSourceListEnabled { get; } + string ExternalSourceInputPort { get; } void AddExternalSource(string connectorId, string key, string name, eExternalSourceType type); void SetExternalSourceState(string key, eExternalSourceMode mode); void ClearExternalSources(); 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 e2a094dc..ea39bb65 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 @@ -407,6 +407,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco CreateOsdSource(); ExternalSourceListEnabled = props.ExternalSourceListEnabled; + ExternalSourceInputPort = props.ExternalSourceInputPort; if (props.UiBranding == null) { @@ -416,6 +417,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco props.UiBranding.BrandingUrl); BrandingEnabled = props.UiBranding.Enable; + _brandingUrl = props.UiBranding.BrandingUrl; } @@ -1917,7 +1919,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco #region IHasExternalSourceSwitching Members /// - /// Weather the Cisco supports External Source Lists or not + /// Wheather the Cisco supports External Source Lists or not /// public bool ExternalSourceListEnabled { @@ -1925,6 +1927,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco private set; } + /// + /// The name of the RoutingInputPort to which the upstream external switcher is connected + /// + public string ExternalSourceInputPort { get; private set; } + public bool BrandingEnabled { get; private set; } private string _brandingUrl; private bool _sendMcUrl; 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 cd280b29..1836bafb 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 @@ -31,9 +31,18 @@ namespace PepperDash.Essentials.Devices.Common.Codec [JsonProperty("sharing")] public SharingProperties Sharing { get; set; } + /// + /// Enables external source switching capability + /// [JsonProperty("externalSourceListEnabled")] public bool ExternalSourceListEnabled { get; set; } + /// + /// The name of the routing input port on the codec to which the external switch is connected + /// + [JsonProperty("externalSourceInputPort")] + public string ExternalSourceInputPort { get; set; } + /// /// Optionsal property to set the limit of any phonebook queries for directory or searching /// From 1dfdd4dd289e9733db5166e8303d6a6a702bd98b Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 12 Nov 2020 16:29:22 -0700 Subject: [PATCH 08/17] Adds StandbyActivate to EndShutdown --- PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index a462ffca..255994fd 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -384,6 +384,7 @@ namespace PepperDash.Essentials { VideoCodec.EndAllCalls(); VideoCodec.StopSharing(); + VideoCodec.StandbyActivate(); SetDefaultLevels(); From 06e8cac5973b3af48777a70a2e5980bd62210ecc Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 12 Nov 2020 16:41:40 -0700 Subject: [PATCH 09/17] Adds more helpful message to Obsolete attribute on IRoutingSinkNoSwitching --- .../PepperDashEssentialsBase/Routing/RoutingInterfaces.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs index 85578c5d..c7f2e533 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs @@ -59,7 +59,7 @@ namespace PepperDash.Essentials.Core /// /// For fixed-source endpoint devices /// - [Obsolete] + [Obsolete("Please switch to IRoutingSink")] public interface IRoutingSinkNoSwitching : IRoutingSink { From ecba28c9cdda621d0c012b8a0926ee36989aee0f Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 13 Nov 2020 13:32:04 -0700 Subject: [PATCH 10/17] Moves the stop sharing and standby commands to later in the EndShutdown() sequence --- 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 255994fd..2ed2da15 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -383,8 +383,6 @@ namespace PepperDash.Essentials protected override void EndShutdown() { VideoCodec.EndAllCalls(); - VideoCodec.StopSharing(); - VideoCodec.StandbyActivate(); SetDefaultLevels(); @@ -395,6 +393,8 @@ namespace PepperDash.Essentials Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room"); RunRouteAction("roomOff"); + VideoCodec.StopSharing(); + VideoCodec.StandbyActivate(); } /// From 2ed9e632c6792e74cd02767186dd758e2e870720 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 13 Nov 2020 14:24:38 -0700 Subject: [PATCH 11/17] Updates to deactivate standby on codec --- .../Room/Types/EssentialsHuddleVtc1Room.cs | 10 + .../Room/EssentialsRoomBase.cs | 712 +++++++++--------- 2 files changed, 366 insertions(+), 356 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index 2ed2da15..b021c2f9 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -592,6 +592,16 @@ namespace PepperDash.Essentials OnFeedback.FireUpdate(); + if (OnFeedback.BoolValue) + { + if (VideoCodec.UsageTracker.InUseTracker.InUseFeedback.BoolValue) + { + Debug.Console(1, this, "Video Codec in use, deactivating standby on codec"); + } + + VideoCodec.StandbyDeactivate(); + } + // report back when done if (successCallback != null) successCallback(); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs index 4cf36470..0043e3b4 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs @@ -1,58 +1,58 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharp.Scheduler; - -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Config; -using PepperDash.Essentials.Core.Devices; -using PepperDash.Essentials.Core.DeviceTypeInterfaces; - -namespace PepperDash.Essentials.Core -{ - /// - /// - /// - public abstract class EssentialsRoomBase : ReconfigurableDevice - { - /// - /// - /// - public BoolFeedback OnFeedback { get; private set; } - - /// - /// Fires when the RoomOccupancy object is set - /// - public event EventHandler RoomOccupancyIsSet; - - public BoolFeedback IsWarmingUpFeedback { get; private set; } - public BoolFeedback IsCoolingDownFeedback { get; private set; } - - public IOccupancyStatusProvider RoomOccupancy { get; private set; } - - public bool OccupancyStatusProviderIsRemote { get; private set; } - - protected abstract Func IsWarmingFeedbackFunc { get; } - protected abstract Func IsCoolingFeedbackFunc { get; } - - /// - /// Indicates if this room is Mobile Control Enabled - /// - public bool IsMobileControlEnabled { get; private set; } - - /// - /// The bridge for this room if Mobile Control is enabled - /// - public IMobileControlRoomBridge MobileControlRoomBridge { get; private set; } - - /// - /// The config name of the source list - /// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharp.Scheduler; + +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Core.Devices; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; + +namespace PepperDash.Essentials.Core +{ + /// + /// + /// + public abstract class EssentialsRoomBase : ReconfigurableDevice + { + /// + /// + /// + public BoolFeedback OnFeedback { get; private set; } + + /// + /// Fires when the RoomOccupancy object is set + /// + public event EventHandler RoomOccupancyIsSet; + + public BoolFeedback IsWarmingUpFeedback { get; private set; } + public BoolFeedback IsCoolingDownFeedback { get; private set; } + + public IOccupancyStatusProvider RoomOccupancy { get; private set; } + + public bool OccupancyStatusProviderIsRemote { get; private set; } + + protected abstract Func IsWarmingFeedbackFunc { get; } + protected abstract Func IsCoolingFeedbackFunc { get; } + + /// + /// Indicates if this room is Mobile Control Enabled + /// + public bool IsMobileControlEnabled { get; private set; } + + /// + /// The bridge for this room if Mobile Control is enabled + /// + public IMobileControlRoomBridge MobileControlRoomBridge { get; private set; } + + /// + /// The config name of the source list + /// /// - protected string _SourceListKey; + protected string _SourceListKey; public virtual string SourceListKey { get { @@ -63,306 +63,306 @@ namespace PepperDash.Essentials.Core _SourceListKey = value; } - } - - /// - /// Timer used for informing the UIs of a shutdown - /// - public SecondsCountdownTimer ShutdownPromptTimer { get; private set; } - - /// - /// - /// - public int ShutdownPromptSeconds { get; set; } - public int ShutdownVacancySeconds { get; set; } - public eShutdownType ShutdownType { get; private set; } - - public EssentialsRoomEmergencyBase Emergency { get; set; } - - public Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; set; } - - public string LogoUrlLightBkgnd { get; set; } - - public string LogoUrlDarkBkgnd { get; set; } - - protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; } - - public eVacancyMode VacancyMode { get; private set; } - - /// - /// Seconds after vacancy prompt is displayed until shutdown - /// - protected int RoomVacancyShutdownSeconds; - - /// - /// Seconds after vacancy detected until prompt is displayed - /// - protected int RoomVacancyShutdownPromptSeconds; - - /// - /// - /// - protected abstract Func OnFeedbackFunc { get; } - - protected Dictionary SavedVolumeLevels = new Dictionary(); - - /// - /// When volume control devices change, should we zero the one that we are leaving? - /// - public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; } - - - public EssentialsRoomBase(DeviceConfig config) - : base(config) - { - // Setup the ShutdownPromptTimer - ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer"); - ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) => - { - if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue) - ShutdownType = eShutdownType.None; - }; - ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered - - ShutdownPromptSeconds = 60; - ShutdownVacancySeconds = 120; - - ShutdownType = eShutdownType.None; - - RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer"); - //RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) => - //{ - // if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue) - // ShutdownType = ShutdownType.Vacancy; - //}; - RoomVacancyShutdownTimer.HasFinished += new EventHandler(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered - - RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning - RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt - VacancyMode = eVacancyMode.None; - - OnFeedback = new BoolFeedback(OnFeedbackFunc); - - IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc); - IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc); - - AddPostActivationAction(() => - { - if (RoomOccupancy != null) - OnRoomOccupancyIsSet(); - }); - } - - public override bool CustomActivate() - { - SetUpMobileControl(); - - return base.CustomActivate(); - } - - /// - /// If mobile control is enabled, sets the appropriate properties - /// - void SetUpMobileControl() - { - var mcBridgeKey = string.Format("mobileControlBridge-{0}", Key); - var mcBridge = DeviceManager.GetDeviceForKey(mcBridgeKey); - if (mcBridge == null) - { - Debug.Console(1, this, "*********************Mobile Control Bridge Not found for this room."); - IsMobileControlEnabled = false; - return; - } - else - { - MobileControlRoomBridge = mcBridge as IMobileControlRoomBridge; - Debug.Console(1, this, "*********************Mobile Control Bridge found and enabled for this room"); - IsMobileControlEnabled = true; - } - } - - void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e) - { - switch (VacancyMode) - { - case eVacancyMode.None: - StartRoomVacancyTimer(eVacancyMode.InInitialVacancy); - break; - case eVacancyMode.InInitialVacancy: - StartRoomVacancyTimer(eVacancyMode.InShutdownWarning); - break; - case eVacancyMode.InShutdownWarning: - { - StartShutdown(eShutdownType.Vacancy); - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting Down due to vacancy."); - break; - } - default: - break; - } - } - - /// - /// - /// - /// - public void StartShutdown(eShutdownType type) - { - // Check for shutdowns running. Manual should override other shutdowns - - if (type == eShutdownType.Manual) - ShutdownPromptTimer.SecondsToCount = ShutdownPromptSeconds; - else if (type == eShutdownType.Vacancy) - ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds; - ShutdownType = type; - ShutdownPromptTimer.Start(); - - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "ShutdownPromptTimer Started. Type: {0}. Seconds: {1}", ShutdownType, ShutdownPromptTimer.SecondsToCount); - } - - public void StartRoomVacancyTimer(eVacancyMode mode) - { - if (mode == eVacancyMode.None) - RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds; - else if (mode == eVacancyMode.InInitialVacancy) - RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds; - else if (mode == eVacancyMode.InShutdownWarning) - RoomVacancyShutdownTimer.SecondsToCount = 60; - VacancyMode = mode; - RoomVacancyShutdownTimer.Start(); - - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Vacancy Timer Started. Mode: {0}. Seconds: {1}", VacancyMode, RoomVacancyShutdownTimer.SecondsToCount); - } - - /// - /// Resets the vacancy mode and shutsdwon the room - /// - public void Shutdown() - { - VacancyMode = eVacancyMode.None; - EndShutdown(); - } - - /// - /// This method is for the derived class to define it's specific shutdown - /// requirements but should not be called directly. It is called by Shutdown() - /// - protected abstract void EndShutdown(); - - - /// - /// Override this to implement a default volume level(s) method - /// - public abstract void SetDefaultLevels(); - - /// - /// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device - /// - /// - public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes) - { - if (statusProvider == null) - { - Debug.Console(0, this, "ERROR: Occupancy sensor device is null"); - return; - } - - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Room Occupancy set to device: '{0}'", (statusProvider as Device).Key); - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Timeout Minutes from Config is: {0}", timeoutMinutes); - - // If status provider is fusion, set flag to remote - if (statusProvider is Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase) - OccupancyStatusProviderIsRemote = true; - - if(timeoutMinutes > 0) - RoomVacancyShutdownSeconds = timeoutMinutes * 60; - - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "RoomVacancyShutdownSeconds set to {0}", RoomVacancyShutdownSeconds); - - RoomOccupancy = statusProvider; - - RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange; - RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange; - - OnRoomOccupancyIsSet(); - } - - void OnRoomOccupancyIsSet() - { - var handler = RoomOccupancyIsSet; - if (handler != null) - handler(this, new EventArgs()); - } - - /// - /// To allow base class to power room on to last source - /// - public abstract void PowerOnToDefaultOrLastSource(); - - /// - /// To allow base class to power room on to default source - /// - /// - public abstract bool RunDefaultPresentRoute(); - - void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e) - { - if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false) - { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Vacancy Detected"); - // Trigger the timer when the room is vacant - StartRoomVacancyTimer(eVacancyMode.InInitialVacancy); - } - else - { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Occupancy Detected"); - // Reset the timer when the room is occupied - RoomVacancyShutdownTimer.Cancel(); - } - } - - /// - /// 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); - } - - /// - /// To describe the various ways a room may be shutting down - /// - public enum eShutdownType - { - None = 0, - External, - Manual, - Vacancy - } - - public enum eVacancyMode - { - None = 0, - InInitialVacancy, - InShutdownWarning - } - - /// - /// - /// - public enum eWarmingCoolingMode - { - None, - Warming, - Cooling - } - - public abstract class EssentialsRoomEmergencyBase : IKeyed - { - public string Key { get; private set; } - - public EssentialsRoomEmergencyBase(string key) - { - Key = key; - } - } + } + + /// + /// Timer used for informing the UIs of a shutdown + /// + public SecondsCountdownTimer ShutdownPromptTimer { get; private set; } + + /// + /// + /// + public int ShutdownPromptSeconds { get; set; } + public int ShutdownVacancySeconds { get; set; } + public eShutdownType ShutdownType { get; private set; } + + public EssentialsRoomEmergencyBase Emergency { get; set; } + + public Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; set; } + + public string LogoUrlLightBkgnd { get; set; } + + public string LogoUrlDarkBkgnd { get; set; } + + protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; } + + public eVacancyMode VacancyMode { get; private set; } + + /// + /// Seconds after vacancy prompt is displayed until shutdown + /// + protected int RoomVacancyShutdownSeconds; + + /// + /// Seconds after vacancy detected until prompt is displayed + /// + protected int RoomVacancyShutdownPromptSeconds; + + /// + /// + /// + protected abstract Func OnFeedbackFunc { get; } + + protected Dictionary SavedVolumeLevels = new Dictionary(); + + /// + /// When volume control devices change, should we zero the one that we are leaving? + /// + public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; } + + + public EssentialsRoomBase(DeviceConfig config) + : base(config) + { + // Setup the ShutdownPromptTimer + ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer"); + ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) => + { + if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue) + ShutdownType = eShutdownType.None; + }; + ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered + + ShutdownPromptSeconds = 60; + ShutdownVacancySeconds = 120; + + ShutdownType = eShutdownType.None; + + RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer"); + //RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) => + //{ + // if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue) + // ShutdownType = ShutdownType.Vacancy; + //}; + RoomVacancyShutdownTimer.HasFinished += new EventHandler(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered + + RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning + RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt + VacancyMode = eVacancyMode.None; + + OnFeedback = new BoolFeedback(OnFeedbackFunc); + + IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc); + IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc); + + AddPostActivationAction(() => + { + if (RoomOccupancy != null) + OnRoomOccupancyIsSet(); + }); + } + + public override bool CustomActivate() + { + SetUpMobileControl(); + + return base.CustomActivate(); + } + + /// + /// If mobile control is enabled, sets the appropriate properties + /// + void SetUpMobileControl() + { + var mcBridgeKey = string.Format("mobileControlBridge-{0}", Key); + var mcBridge = DeviceManager.GetDeviceForKey(mcBridgeKey); + if (mcBridge == null) + { + Debug.Console(1, this, "*********************Mobile Control Bridge Not found for this room."); + IsMobileControlEnabled = false; + return; + } + else + { + MobileControlRoomBridge = mcBridge as IMobileControlRoomBridge; + Debug.Console(1, this, "*********************Mobile Control Bridge found and enabled for this room"); + IsMobileControlEnabled = true; + } + } + + void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e) + { + switch (VacancyMode) + { + case eVacancyMode.None: + StartRoomVacancyTimer(eVacancyMode.InInitialVacancy); + break; + case eVacancyMode.InInitialVacancy: + StartRoomVacancyTimer(eVacancyMode.InShutdownWarning); + break; + case eVacancyMode.InShutdownWarning: + { + StartShutdown(eShutdownType.Vacancy); + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting Down due to vacancy."); + break; + } + default: + break; + } + } + + /// + /// + /// + /// + public void StartShutdown(eShutdownType type) + { + // Check for shutdowns running. Manual should override other shutdowns + + if (type == eShutdownType.Manual) + ShutdownPromptTimer.SecondsToCount = ShutdownPromptSeconds; + else if (type == eShutdownType.Vacancy) + ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds; + ShutdownType = type; + ShutdownPromptTimer.Start(); + + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "ShutdownPromptTimer Started. Type: {0}. Seconds: {1}", ShutdownType, ShutdownPromptTimer.SecondsToCount); + } + + public void StartRoomVacancyTimer(eVacancyMode mode) + { + if (mode == eVacancyMode.None) + RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds; + else if (mode == eVacancyMode.InInitialVacancy) + RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds; + else if (mode == eVacancyMode.InShutdownWarning) + RoomVacancyShutdownTimer.SecondsToCount = 60; + VacancyMode = mode; + RoomVacancyShutdownTimer.Start(); + + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Vacancy Timer Started. Mode: {0}. Seconds: {1}", VacancyMode, RoomVacancyShutdownTimer.SecondsToCount); + } + + /// + /// Resets the vacancy mode and shutsdwon the room + /// + public void Shutdown() + { + VacancyMode = eVacancyMode.None; + EndShutdown(); + } + + /// + /// This method is for the derived class to define it's specific shutdown + /// requirements but should not be called directly. It is called by Shutdown() + /// + protected abstract void EndShutdown(); + + + /// + /// Override this to implement a default volume level(s) method + /// + public abstract void SetDefaultLevels(); + + /// + /// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device + /// + /// + public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes) + { + if (statusProvider == null) + { + Debug.Console(0, this, "ERROR: Occupancy sensor device is null"); + return; + } + + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Room Occupancy set to device: '{0}'", (statusProvider as Device).Key); + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Timeout Minutes from Config is: {0}", timeoutMinutes); + + // If status provider is fusion, set flag to remote + if (statusProvider is Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase) + OccupancyStatusProviderIsRemote = true; + + if(timeoutMinutes > 0) + RoomVacancyShutdownSeconds = timeoutMinutes * 60; + + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "RoomVacancyShutdownSeconds set to {0}", RoomVacancyShutdownSeconds); + + RoomOccupancy = statusProvider; + + RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange; + RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange; + + OnRoomOccupancyIsSet(); + } + + void OnRoomOccupancyIsSet() + { + var handler = RoomOccupancyIsSet; + if (handler != null) + handler(this, new EventArgs()); + } + + /// + /// To allow base class to power room on to last source + /// + public abstract void PowerOnToDefaultOrLastSource(); + + /// + /// To allow base class to power room on to default source + /// + /// + public abstract bool RunDefaultPresentRoute(); + + void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e) + { + if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false) + { + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Vacancy Detected"); + // Trigger the timer when the room is vacant + StartRoomVacancyTimer(eVacancyMode.InInitialVacancy); + } + else + { + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Occupancy Detected"); + // Reset the timer when the room is occupied + RoomVacancyShutdownTimer.Cancel(); + } + } + + /// + /// 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); + } + + /// + /// To describe the various ways a room may be shutting down + /// + public enum eShutdownType + { + None = 0, + External, + Manual, + Vacancy + } + + public enum eVacancyMode + { + None = 0, + InInitialVacancy, + InShutdownWarning + } + + /// + /// + /// + public enum eWarmingCoolingMode + { + None, + Warming, + Cooling + } + + public abstract class EssentialsRoomEmergencyBase : IKeyed + { + public string Key { get; private set; } + + public EssentialsRoomEmergencyBase(string key) + { + Key = key; + } + } } \ No newline at end of file From 1d184f0f5e409eb3e1fa4fb0b510407f64c5b3af Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 13 Nov 2020 14:46:15 -0700 Subject: [PATCH 12/17] Updates to deactivate standby on codec --- PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index b021c2f9..efb0ad7b 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -599,7 +599,10 @@ namespace PepperDash.Essentials Debug.Console(1, this, "Video Codec in use, deactivating standby on codec"); } - VideoCodec.StandbyDeactivate(); + if (VideoCodec.StandbyIsOnFeedback.BoolValue) + { + VideoCodec.StandbyDeactivate(); + } } // report back when done From ccdd8005d02846e448c4f3d4bd34f0567d6cc3c1 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 13 Nov 2020 14:54:26 -0700 Subject: [PATCH 13/17] Fixes inverted standby state feedback --- .../VideoCodec/CiscoCodec/xStatus.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 9af52bd2..9ec4fa44 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 @@ -1368,8 +1368,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { set { - // If the incoming value is "Of" it sets the BoolValue true, otherwise sets it false - BoolValue = value == "Off"; + // If the incoming value is "On" it sets the BoolValue true, otherwise sets it false + BoolValue = value == "On"; OnValueChanged(); } } From 1d1b4f07909b6e8cafa4df283e420c3aef85da11 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 13 Nov 2020 15:43:48 -0700 Subject: [PATCH 14/17] update mobileControl retrieval method remove commented out MC stuff --- PepperDashEssentials/ControlSystem.cs | 45 ++++++++++++++------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index 9f8022de..5977e3e9 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -290,33 +290,14 @@ namespace PepperDash.Essentials DeviceManager.ActivateAll(); - var mobileControl = DeviceManager.GetDeviceForKey("appServer") as IMobileControl; + var mobileControl = GetMobileControlDevice(); if (mobileControl == null) return; mobileControl.LinkSystemMonitorToAppServer(); - //LinkSystemMonitorToAppServer(); + } - //void LinkSystemMonitorToAppServer() - //{ - // var sysMon = DeviceManager.GetDeviceForKey("systemMonitor") as PepperDash.Essentials.Core.Monitoring.SystemMonitorController; - - // var appServer = DeviceManager.GetDeviceForKey("appServer") as MobileControlSystemController; - - - // if (sysMon != null && appServer != null) - // { - // var key = sysMon.Key + "-" + appServer.Key; - // var messenger = new PepperDash.Essentials.AppServer.Messengers.SystemMonitorMessenger - // (key, sysMon, "/device/systemMonitor"); - - // messenger.RegisterWithAppServer(appServer); - - // DeviceManager.AddDevice(messenger); - // } - //} - /// /// Reads all devices from config and adds them to DeviceManager /// @@ -504,7 +485,7 @@ namespace PepperDash.Essentials private static void CreateMobileControlBridge(EssentialsRoomBase room) { - var mobileControl = DeviceManager.GetDeviceForKey("appServer") as IMobileControl; + var mobileControl = GetMobileControlDevice(); if (mobileControl == null) return; @@ -513,6 +494,26 @@ namespace PepperDash.Essentials Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control Bridge Added..."); } + private static IMobileControl GetMobileControlDevice() + { + var mobileControlList = DeviceManager.AllDevices.OfType().ToList(); + + if (mobileControlList.Count > 0) + { + Debug.Console(0, Debug.ErrorLogLevel.Notice, + "Multiple instances of Mobile Control Server found. Using instance with key {0}", + mobileControlList[0].Key); + } + + if (mobileControlList.Count != 0) + { + return mobileControlList[0]; + } + + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control not enabled for this system"); + return null; + } + /// /// Helps add the post activation steps that link bridges to main controller /// From b5337572c4691196c6b6b736802736879644959c Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 13 Nov 2020 15:44:02 -0700 Subject: [PATCH 15/17] update nuspec for correct dependencies --- .../PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec index d5bb4a57..5db86afc 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec @@ -14,7 +14,7 @@ crestron 3series 4series - + From 14c3914e5cb9d78393fc4eb75cea8596c38cc09c Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 13 Nov 2020 15:53:02 -0700 Subject: [PATCH 16/17] remove commented-out MC Stuff --- PepperDashEssentials/ControlSystem.cs | 36 +------------------ .../DeviceTypeInterfaces/IMobileControl.cs | 4 +-- 2 files changed, 2 insertions(+), 38 deletions(-) diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index 5977e3e9..2188f1b0 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -16,7 +16,6 @@ using PepperDash.Essentials.Devices.Common; using PepperDash.Essentials.DM; using PepperDash.Essentials.Fusion; using PepperDash.Essentials.Room.Config; -//using PepperDash.Essentials.Room.MobileControl; using Newtonsoft.Json; using PepperDash.Essentials.Core.DeviceTypeInterfaces; @@ -375,11 +374,6 @@ namespace PepperDash.Essentials if (newDev == null) newDev = PepperDash.Essentials.Core.DeviceFactory.GetDevice(devConf); - // - //if (newDev == null) - // newDev = PepperDash.Essentials.Devices.Displays.DisplayDeviceFactory.GetDevice(devConf); - // - if (newDev != null) DeviceManager.AddDevice(newDev); else @@ -446,10 +440,6 @@ namespace PepperDash.Essentials Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); - // Mobile Control bridge - //var bridge = new MobileConrolEssentialsHuddleSpaceRoomBridge(room as EssentialsHuddleSpaceRoom); - //AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present - //DeviceManager.AddDevice(bridge); CreateMobileControlBridge(room); } @@ -461,10 +451,6 @@ namespace PepperDash.Essentials DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1)); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); - // Mobile Control bridge - //var bridge = new MobileConrolEssentialsHuddleSpaceRoomBridge(room); - //AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present - //DeviceManager.AddDevice(bridge); CreateMobileControlBridge(room); } @@ -489,7 +475,7 @@ namespace PepperDash.Essentials if (mobileControl == null) return; - mobileControl.CreateMobileControlRoomBridge(room); + mobileControl.CreateMobileControlRoomBridge(room, mobileControl); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control Bridge Added..."); } @@ -514,26 +500,6 @@ namespace PepperDash.Essentials return null; } - /// - /// Helps add the post activation steps that link bridges to main controller - /// - /// - //void AddBridgePostActivationHelper(MobileControlBridgeBase bridge) - //{ - // bridge.AddPostActivationAction(() => - // { - // var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as MobileControlSystemController; - // if (parent == null) - // { - // Debug.Console(0, bridge, "ERROR: Cannot connect app server room bridge. System controller not present"); - // return; - // } - // Debug.Console(0, bridge, "Linking to parent controller"); - // bridge.AddParent(parent); - // parent.AddBridge(bridge); - // }); - //} - /// /// Fires up a logo server if not already running /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs index 6f4ff344..2dfa7c41 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs @@ -8,11 +8,9 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces /// public interface IMobileControl : IKeyed { - void CreateMobileControlRoomBridge(EssentialsRoomBase room); + void CreateMobileControlRoomBridge(EssentialsRoomBase room, IMobileControl parent); void LinkSystemMonitorToAppServer(); - - IMobileControl GetAppServer(); } /// From 3f9d306a341059d754a11dc5457bba6822f1ff61 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 13 Nov 2020 16:03:02 -0700 Subject: [PATCH 17/17] fix conditions for getting mc --- PepperDashEssentials/ControlSystem.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index 2188f1b0..2801e561 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -484,14 +484,15 @@ namespace PepperDash.Essentials { var mobileControlList = DeviceManager.AllDevices.OfType().ToList(); - if (mobileControlList.Count > 0) + if (mobileControlList.Count > 1) { - Debug.Console(0, Debug.ErrorLogLevel.Notice, - "Multiple instances of Mobile Control Server found. Using instance with key {0}", - mobileControlList[0].Key); + Debug.Console(0, Debug.ErrorLogLevel.Warning, + "Multiple instances of Mobile Control Server found."); + + return null; } - if (mobileControlList.Count != 0) + if (mobileControlList.Count > 0) { return mobileControlList[0]; }