From c8b0c7dd01277ed0df238ba3ffd4239216d1eaca Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 20 Jul 2021 17:12:42 -0600 Subject: [PATCH 01/19] #753 Adds new type and starts updating as needed --- .../PepperDashEssentials.csproj | 1 + .../Types/EssentialsCombinedHuddleVtc1Room.cs | 813 ++++++++++++++++++ .../Room/Combining/EssentialsRoomCombiner.cs | 2 - .../EssentialsRoomCombinerPropertiesConfig.cs | 3 + 4 files changed, 817 insertions(+), 2 deletions(-) create mode 100644 PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs diff --git a/PepperDashEssentials/PepperDashEssentials.csproj b/PepperDashEssentials/PepperDashEssentials.csproj index d172076a..e4a0cff6 100644 --- a/PepperDashEssentials/PepperDashEssentials.csproj +++ b/PepperDashEssentials/PepperDashEssentials.csproj @@ -144,6 +144,7 @@ + diff --git a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs new file mode 100644 index 00000000..1be38cb0 --- /dev/null +++ b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs @@ -0,0 +1,813 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +using Newtonsoft.Json; + +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Room.Config; +using PepperDash.Essentials.Devices.Common.Codec; +using PepperDash.Essentials.Devices.Common.VideoCodec; +using PepperDash.Essentials.Devices.Common.AudioCodec; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; + +namespace PepperDash.Essentials +{ + public class EssentialsCombinedHuddleVtc1Room : EssentialsRoomBase, IEssentialsHuddleVtc1Room + { + private bool _codecExternalSourceChange; + public event EventHandler CurrentVolumeDeviceChange; + public event SourceInfoChangeHandler CurrentSourceChange; + + + //************************ + // Call-related stuff + + public BoolFeedback InCallFeedback { get; private set; } + + ///// + ///// Make this more specific + ///// + //public List ActiveCalls { get; private set; } + + /// + /// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis + /// + public IntFeedback CallTypeFeedback { get; private set; } + + /// + /// + /// + public BoolFeedback PrivacyModeIsOnFeedback { get; private set; } + + /// + /// When something in the room is sharing with the far end or through other means + /// + public BoolFeedback IsSharingFeedback { get; private set; } + + //************************ + + protected override Func OnFeedbackFunc + { + get + { + return () => + { + var disp = DefaultDisplay as DisplayBase; + var val = CurrentSourceInfo != null + && CurrentSourceInfo.Type == eSourceListItemType.Route + && disp != null; + //&& disp.PowerIsOnFeedback.BoolValue; + return val; + }; + } + } + /// + /// + /// + protected override Func IsWarmingFeedbackFunc + { + get + { + return () => + { + var disp = DefaultDisplay as DisplayBase; + if (disp != null) + return disp.IsWarmingUpFeedback.BoolValue; + else + return false; + }; + } + } + /// + /// + /// + protected override Func IsCoolingFeedbackFunc + { + get + { + return () => + { + var disp = DefaultDisplay as DisplayBase; + if (disp != null) + return disp.IsCoolingDownFeedback.BoolValue; + else + return false; + }; + } + } + + public EssentialsConferenceRoomPropertiesConfig PropertiesConfig { get; private set; } + + private List Displays; + + public IRoutingSinkWithSwitching DefaultDisplay { get; private set; } + + public IBasicVolumeControls DefaultAudioDevice { get; private set; } + public IBasicVolumeControls DefaultVolumeControls { get; private set; } + + public VideoCodecBase VideoCodec { get; private set; } + + public AudioCodecBase AudioCodec { get; private set; } + + public bool ExcludeFromGlobalFunctions { get; set; } + + public string DefaultSourceItem { get; set; } + + public ushort DefaultVolume { get; set; } + + /// + /// If room is off, enables power on to last source. Default true + /// + public bool EnablePowerOnToLastSource { get; set; } + string LastSourceKey; + + /// + /// Sets the volume control device, and attaches/removes InUseTrackers with "audio" + /// tag to device. + /// + public IBasicVolumeControls CurrentVolumeControls + { + get { return _CurrentAudioDevice; } + set + { + if (value == _CurrentAudioDevice) return; + + var oldDev = _CurrentAudioDevice; + // derigister this room from the device, if it can + if (oldDev is IInUseTracking) + (oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio"); + var handler = CurrentVolumeDeviceChange; + if (handler != null) + CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange)); + _CurrentAudioDevice = value; + if (handler != null) + CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange)); + // register this room with new device, if it can + if (_CurrentAudioDevice is IInUseTracking) + (_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio"); + } + } + IBasicVolumeControls _CurrentAudioDevice; + + /// + /// The SourceListItem last run - containing names and icons + /// + public SourceListItem CurrentSourceInfo + { + get { return _CurrentSourceInfo; } + set + { + if (value == _CurrentSourceInfo) return; + + var handler = CurrentSourceChange; + // remove from in-use tracker, if so equipped + if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking) + (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control"); + + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.WillChange); + + _CurrentSourceInfo = value; + + // add to in-use tracking + if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking) + (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control"); + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.DidChange); + + var vc = VideoCodec as IHasExternalSourceSwitching; + if (vc != null && !_codecExternalSourceChange) + { + vc.SetSelectedSource(CurrentSourceInfoKey); + } + + _codecExternalSourceChange = false; + } + } + SourceListItem _CurrentSourceInfo; + + public string CurrentSourceInfoKey { get; set; } + + /// + /// "codecOsd" + /// + public string DefaultCodecRouteString { get { return "codecOsd"; } } + + /// + /// Temporary implementation. Returns the schedule-ready object or null if none. Fow now, + /// always returns the VideoCodec if it is capable + /// + public IHasScheduleAwareness ScheduleSource { get { return VideoCodec as IHasScheduleAwareness; } } + + CCriticalSection SourceSelectLock = new CCriticalSection(); + + public EssentialsCombinedHuddleVtc1Room(DeviceConfig config) + : base(config) + { + try + { + PropertiesConfig = JsonConvert.DeserializeObject + (config.Properties.ToString()); + DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching; + + VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as + PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase; + + + if (VideoCodec == null) + throw new ArgumentNullException("codec cannot be null"); + + AudioCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.AudioCodecKey) as + PepperDash.Essentials.Devices.Common.AudioCodec.AudioCodecBase; + if (AudioCodec == null) + Debug.Console(0, this, "No Audio Codec Found"); + + DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls; + + Initialize(); + } + catch (Exception e) + { + Debug.Console(1, this, "Error building room: \n{0}", e); + } + } + + void Initialize() + { + try + { + if (DefaultAudioDevice is IBasicVolumeControls) + DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls; + else if (DefaultAudioDevice is IHasVolumeDevice) + DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice; + CurrentVolumeControls = DefaultVolumeControls; + + + // Combines call feedback from both codecs if available + InCallFeedback = new BoolFeedback(() => + { + bool inAudioCall = false; + bool inVideoCall = false; + + if (AudioCodec != null) + inAudioCall = AudioCodec.IsInCall; + + if (VideoCodec != null) + inVideoCall = VideoCodec.IsInCall; + + if (inAudioCall || inVideoCall) + return true; + else + return false; + }); + + var disp = DefaultDisplay as DisplayBase; + if (disp != null) + { + // Link power, warming, cooling to display + var dispTwoWay = disp as IHasPowerControlWithFeedback; + if (dispTwoWay != null) + { + dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) => + { + if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) + { + if (!dispTwoWay.PowerIsOnFeedback.BoolValue) + CurrentSourceInfo = null; + OnFeedback.FireUpdate(); + } + if (dispTwoWay.PowerIsOnFeedback.BoolValue) + { + SetDefaultLevels(); + } + }; + } + + disp.IsWarmingUpFeedback.OutputChange += (o, a) => + { + IsWarmingUpFeedback.FireUpdate(); + if (!IsWarmingUpFeedback.BoolValue) + (CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume); + }; + disp.IsCoolingDownFeedback.OutputChange += (o, a) => + { + IsCoolingDownFeedback.FireUpdate(); + }; + + } + + + + // Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback + this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this); + + Debug.Console(2, this, "Microphone Privacy Config evaluated."); + + // Get emergency object, if any + this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this); + + Debug.Console(2, this, "Emergency Config evaluated."); + + + VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); + VideoCodec.IsReadyChange += (o, a) => { this.SetCodecExternalSources(); SetCodecBranding(); }; + + if (AudioCodec != null) + AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); + + IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue); + VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate(); + + // link privacy to VC (for now?) + PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue); + VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate(); + + CallTypeFeedback = new IntFeedback(() => 0); + + SetSourceListKey(); + + EnablePowerOnToLastSource = true; + } + catch (Exception e) + { + Debug.Console(0, this, "Error Initializing Room: {0}", e); + } + } + + private void SetSourceListKey() + { + if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey)) + { + SetSourceListKey(PropertiesConfig.SourceListKey); + } + else + { + SetSourceListKey(Key); + } + + SetCodecExternalSources(); + } + + protected override void CustomSetConfig(DeviceConfig config) + { + var newPropertiesConfig = JsonConvert.DeserializeObject(config.Properties.ToString()); + + if (newPropertiesConfig != null) + PropertiesConfig = newPropertiesConfig; + + ConfigWriter.UpdateRoomConfig(config); + } + + public override bool CustomActivate() + { + // Add Occupancy object from config + if (PropertiesConfig.Occupancy != null) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room"); + this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as + IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes); + } + + this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight(); + this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark(); + + this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem; + this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100); + + return base.CustomActivate(); + } + + /// + /// + /// + protected override void EndShutdown() + { + VideoCodec.EndAllCalls(); + + SetDefaultLevels(); + + RunDefaultPresentRoute(); + + CrestronEnvironment.Sleep(1000); + + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room"); + + RunRouteAction("roomOff"); + VideoCodec.StopSharing(); + VideoCodec.StandbyActivate(); + } + + /// + /// Routes the default source item, if any. Returns true when default route exists + /// + public override bool RunDefaultPresentRoute() + { + if (DefaultSourceItem != null) + RunRouteAction(DefaultSourceItem); + + return DefaultSourceItem != null; + } + + /// + /// Sets up the room when started into call mode without presenting a source + /// + /// + public bool RunDefaultCallRoute() + { + RunRouteAction(DefaultCodecRouteString); + return true; + } + + public void RunRouteActionCodec(string routeKey, string sourceListKey) + { + _codecExternalSourceChange = true; + RunRouteAction(routeKey, sourceListKey); + } + + /// + /// + /// + /// + public void RunRouteAction(string routeKey) + { + RunRouteAction(routeKey, new Action(() => { })); + } + + /// + /// + /// + /// + /// + /// + public void RunRouteAction(string routeKey, string sourceListKey) + { + if (string.IsNullOrEmpty(sourceListKey)) + { + Debug.Console(1, this, "No sourceListKey present. RunRouteAction assumes default source list."); + RunRouteAction(routeKey, new Action(() => { })); + } + else + { + Debug.Console(1, this, "sourceListKey present but not yet implemented"); + throw new NotImplementedException(); + } + } + + /// + /// + /// + /// + /// + /// + public void RunRouteAction(string routeKey, string sourceListKey, Action successCallback) + { + if (string.IsNullOrEmpty(sourceListKey)) + { + RunRouteAction(routeKey, successCallback); + } + else + throw new NotImplementedException(); + } + + + /// + /// Gets a source from config list SourceListKey and dynamically build and executes the + /// route or commands + /// + /// + public void RunRouteAction(string routeKey, Action successCallback) + { + // Run this on a separate thread + new CTimer(o => + { + // try to prevent multiple simultaneous selections + SourceSelectLock.TryEnter(); + + try + { + + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Run route action '{0}'", routeKey); + var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey); + if (dict == null) + { + Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey); + return; + } + + // Try to get the list item by it's string key + if (!dict.ContainsKey(routeKey)) + { + Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'", + routeKey, SourceListKey); + return; + } + + // End usage timer on last source + if (!string.IsNullOrEmpty(LastSourceKey)) + { + var usageLastSource = dict[LastSourceKey].SourceDevice as IUsageTracking; + if (usageLastSource != null && usageLastSource.UsageTracker != null) + { + try + { + // There MAY have been failures in here. Protect + usageLastSource.UsageTracker.EndDeviceUsage(); + } + catch (Exception e) + { + Debug.Console(1, this, "*#* EXCEPTION in end usage tracking:\r{0}", e); + } + } + } + + // Let's run it + var item = dict[routeKey]; + if (routeKey.ToLower() != "roomoff") + { + + LastSourceKey = routeKey; + } + else + CurrentSourceInfoKey = null; + + // hand off the individual routes to this helper + foreach (var route in item.RouteList) + DoRouteItem(route); + + // Start usage timer on routed source + var usageNewSource = item.SourceDevice as IUsageTracking; + if (usageNewSource != null && usageNewSource.UsageTracker != null) // Have to make sure there is a usage tracker! + { + (item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage(); + } + + // See if this can be moved into common, base-class method ------------- + + + // Set volume control, using default if non provided + IBasicVolumeControls volDev = null; + // Handle special cases for volume control + if (string.IsNullOrEmpty(item.VolumeControlKey) + || item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase)) + volDev = DefaultVolumeControls; + else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) + volDev = DefaultDisplay as IBasicVolumeControls; + // Or a specific device, probably rarely used. + else + { + var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey); + if (dev is IBasicVolumeControls) + volDev = dev as IBasicVolumeControls; + else if (dev is IHasVolumeDevice) + volDev = (dev as IHasVolumeDevice).VolumeDevice; + } + + if (volDev != CurrentVolumeControls) + { + // zero the volume on the device we are leaving. + // Set the volume to default on device we are entering + if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback) + { + var vd = CurrentVolumeControls as IBasicVolumeWithFeedback; + SavedVolumeLevels[vd] = (uint)vd.VolumeLevelFeedback.IntValue; + vd.SetVolume(0); + } + + CurrentVolumeControls = volDev; + if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback) + { + var vd = CurrentVolumeControls as IBasicVolumeWithFeedback; + ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume); + vd.SetVolume(vol); + } + } + // ----------------------------------------------------------------------- + + + + // store the name and UI info for routes + if (item.SourceKey == "$off") + { + CurrentSourceInfoKey = routeKey; + CurrentSourceInfo = null; + } + else if (item.SourceKey != null) + { + CurrentSourceInfoKey = routeKey; + CurrentSourceInfo = item; + } + + 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(); + } + + if (VideoCodec.StandbyIsOnFeedback.BoolValue) + { + VideoCodec.StandbyDeactivate(); + } + else + { + Debug.Console(1, this, "Video codec not in standby. No need to wake."); + } + } + else + { + Debug.Console(1, this, "Room OnFeedback state: {0}", OnFeedback.BoolValue); + } + + // report back when done + if (successCallback != null) + successCallback(); + } + catch (Exception e) + { + Debug.Console(1, this, "ERROR in routing: {0}", e); + } + + SourceSelectLock.Leave(); + }, 0); // end of CTimer + } + + /// + /// + /// + /// + void DoRouteItem(SourceRouteListItem route) + { + // if there is a $defaultAll on route, run two separate + if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase)) + { + // Going to assume a single-path route for now + var tempVideo = new SourceRouteListItem + { + DestinationKey = "$defaultDisplay", + SourceKey = route.SourceKey, + Type = eRoutingSignalType.Video + }; + DoRoute(tempVideo); + } + else + DoRoute(route); + } + + /// + /// + /// + /// + /// + bool DoRoute(SourceRouteListItem route) + { + IRoutingSink dest = null; + + if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase)) + dest = DefaultAudioDevice as IRoutingSinkNoSwitching; + else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) + dest = DefaultDisplay; + else + dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching; + + if (dest == null) + { + Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey); + return false; + } + + if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase)) + { + dest.ReleaseRoute(); + if (dest is IHasPowerControl) + (dest as IHasPowerControl).PowerOff(); + + } + else + { + var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs; + if (source == null) + { + Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey); + return false; + } + dest.ReleaseAndMakeRoute(source, route.Type); + } + return true; + } + + public override void RoomVacatedForTimeoutPeriod(object o) + { + //Implement this + } + + /// + /// Does what it says + /// + public override void SetDefaultLevels() + { + Debug.Console(1, this, "Restoring default levels"); + var vc = CurrentVolumeControls as IBasicVolumeWithFeedback; + if (vc != null) + vc.SetVolume(DefaultVolume); + } + /// + /// Will power the room on with the last-used source + /// + public override void PowerOnToDefaultOrLastSource() + { + if (!EnablePowerOnToLastSource || LastSourceKey == null) + return; + RunRouteAction(LastSourceKey); + } + + /// + /// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions + /// + public static void AllRoomsOff() + { + var allRooms = DeviceManager.AllDevices.Where(d => + d is IEssentialsRoom && !(d as IEssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions); + foreach (var room in allRooms) + (room as IEssentialsHuddleSpaceRoom).RunRouteAction("roomOff"); + } + + + /// + /// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch + /// + private void SetCodecExternalSources() + { + var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching; + + if (videoCodecWithExternalSwitching == null || !videoCodecWithExternalSwitching.ExternalSourceListEnabled) + { + return; + } + + 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; + + videoCodecWithExternalSwitching.ClearExternalSources(); + videoCodecWithExternalSwitching.RunRouteAction = RunRouteActionCodec; + var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ; + + foreach (var kvp in srcList) + { + var srcConfig = kvp.Value; + + 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() + { + var vcWithBranding = VideoCodec as IHasBranding; + + if (vcWithBranding == null) return; + + Debug.Console(1, this, "Setting Codec Branding"); + vcWithBranding.InitializeBranding(Key); + } + + #region IPrivacy Members + + + public void PrivacyModeOff() + { + VideoCodec.PrivacyModeOff(); + } + + public void PrivacyModeOn() + { + VideoCodec.PrivacyModeOn(); + } + + public void PrivacyModeToggle() + { + VideoCodec.PrivacyModeToggle(); + } + + #endregion + + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs index 6d80913f..00c55d1c 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs @@ -59,8 +59,6 @@ namespace PepperDash.Essentials.Core void CreateScenarios() { - RoomCombinationScenarios = new List(); - foreach (var scenarioConfig in _propertiesConfig.Scenarios) { var scenario = new RoomCombinationScenario(scenarioConfig); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs index 05295f42..9d721584 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs @@ -87,6 +87,9 @@ namespace PepperDash.Essentials.Core [JsonProperty("partitionStates")] public List PartitionStates { get; set; } + /// + /// Determines which UI devices get mapped to which room in this scenario. The Key should be the key of the UI device and the Value should be the key of the room to map to + /// [JsonProperty("uiMap")] public Dictionary UiMap { get; set; } From 61d8370329ef74c90c0862d9f3f93f382baa78fd Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 20 Jul 2021 17:27:30 -0600 Subject: [PATCH 02/19] Updates to config type in IEssentialsHuddleVtc1Room --- .../Types/EssentialsCombinedHuddleVtc1Room.cs | 78 ++++++++++--------- .../Room/Types/EssentialsHuddleVtc1Room.cs | 4 +- .../Interfaces/IEssentialsHuddleVtc1Room.cs | 2 +- 3 files changed, 44 insertions(+), 40 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs index 1be38cb0..7f140ff3 100644 --- a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs @@ -213,7 +213,6 @@ namespace PepperDash.Essentials { PropertiesConfig = JsonConvert.DeserializeObject (config.Properties.ToString()); - DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching; VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase; @@ -266,42 +265,7 @@ namespace PepperDash.Essentials return false; }); - var disp = DefaultDisplay as DisplayBase; - if (disp != null) - { - // Link power, warming, cooling to display - var dispTwoWay = disp as IHasPowerControlWithFeedback; - if (dispTwoWay != null) - { - dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) => - { - if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) - { - if (!dispTwoWay.PowerIsOnFeedback.BoolValue) - CurrentSourceInfo = null; - OnFeedback.FireUpdate(); - } - if (dispTwoWay.PowerIsOnFeedback.BoolValue) - { - SetDefaultLevels(); - } - }; - } - - disp.IsWarmingUpFeedback.OutputChange += (o, a) => - { - IsWarmingUpFeedback.FireUpdate(); - if (!IsWarmingUpFeedback.BoolValue) - (CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume); - }; - disp.IsCoolingDownFeedback.OutputChange += (o, a) => - { - IsCoolingDownFeedback.FireUpdate(); - }; - - } - - + SetupDisplays(); // Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this); @@ -339,6 +303,46 @@ namespace PepperDash.Essentials } } + private void SetupDisplays() + { + //DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching; + + var disp = DefaultDisplay as DisplayBase; + if (disp != null) + { + // Link power, warming, cooling to display + var dispTwoWay = disp as IHasPowerControlWithFeedback; + if (dispTwoWay != null) + { + dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) => + { + if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) + { + if (!dispTwoWay.PowerIsOnFeedback.BoolValue) + CurrentSourceInfo = null; + OnFeedback.FireUpdate(); + } + if (dispTwoWay.PowerIsOnFeedback.BoolValue) + { + SetDefaultLevels(); + } + }; + } + + disp.IsWarmingUpFeedback.OutputChange += (o, a) => + { + IsWarmingUpFeedback.FireUpdate(); + if (!IsWarmingUpFeedback.BoolValue) + (CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume); + }; + disp.IsCoolingDownFeedback.OutputChange += (o, a) => + { + IsCoolingDownFeedback.FireUpdate(); + }; + + } + } + private void SetSourceListKey() { if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey)) diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index 5e7b5c37..14fa93e1 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -101,7 +101,7 @@ namespace PepperDash.Essentials } } - public EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; private set; } + public EssentialsConferenceRoomPropertiesConfig PropertiesConfig { get; private set; } public IRoutingSinkWithSwitching DefaultDisplay { get; private set; } public IBasicVolumeControls DefaultAudioDevice { get; private set; } @@ -210,7 +210,7 @@ namespace PepperDash.Essentials { PropertiesConfig = JsonConvert.DeserializeObject (config.Properties.ToString()); - DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching; + DefaultDisplay = DeviceManager.GetDeviceForKey((PropertiesConfig as EssentialsHuddleVtc1PropertiesConfig).DefaultDisplayKey) as IRoutingSinkWithSwitching; VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase; diff --git a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs index 5a6e9f59..f3988cb2 100644 --- a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs @@ -10,7 +10,7 @@ namespace PepperDash.Essentials public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange, IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback { - EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; } + EssentialsConferenceRoomPropertiesConfig PropertiesConfig { get; } void RunRouteAction(string routeKey); From 56f9a29c612b66a080b4921bc9f6970c423f0de0 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 21 Jul 2021 14:19:57 -0600 Subject: [PATCH 03/19] #753 Updates some of the Funcs --- .../Types/EssentialsCombinedHuddleVtc1Room.cs | 77 +++++++++++++++++-- .../Interfaces/IEssentialsHuddleVtc1Room.cs | 2 + 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs index 7f140ff3..de4b26ec 100644 --- a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs @@ -75,9 +75,18 @@ namespace PepperDash.Essentials { return () => { - var disp = DefaultDisplay as DisplayBase; - if (disp != null) - return disp.IsWarmingUpFeedback.BoolValue; + var displays = Displays.Where((d) => d is TwoWayDisplayBase) as List; + if (displays != null) + { + var warmingDisplays = displays.Where((d) => d.IsWarmingUpFeedback.BoolValue); + + if (warmingDisplays.Count() > 0) + { + return true; + } + else + return false; + } else return false; }; @@ -92,9 +101,18 @@ namespace PepperDash.Essentials { return () => { - var disp = DefaultDisplay as DisplayBase; - if (disp != null) - return disp.IsCoolingDownFeedback.BoolValue; + var displays = Displays.Where((d) => d is TwoWayDisplayBase) as List; + if (displays != null) + { + var coolingDisplays = displays.Where((d) => d.IsCoolingDownFeedback.BoolValue); + + if (coolingDisplays.Count() > 0) + { + return true; + } + else + return false; + } else return false; }; @@ -307,6 +325,53 @@ namespace PepperDash.Essentials { //DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching; + var destinationList = ConfigReader.ConfigObject.DestinationLists[PropertiesConfig.DestinationListKey]; + + foreach (var destination in destinationList) + { + var dest = destination.Value.SinkDevice as IRoutingSinkWithSwitching; + + if (dest != null) + { + Displays.Add(dest); + } + + var display = dest as DisplayBase; + if (display != null) + { + // Link power, warming, cooling to display + var dispTwoWay = display as IHasPowerControlWithFeedback; + if (dispTwoWay != null) + { + dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) => + { + if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) + { + if (!dispTwoWay.PowerIsOnFeedback.BoolValue) + CurrentSourceInfo = null; + OnFeedback.FireUpdate(); + } + if (dispTwoWay.PowerIsOnFeedback.BoolValue) + { + SetDefaultLevels(); + } + }; + } + + display.IsWarmingUpFeedback.OutputChange += (o, a) => + { + IsWarmingUpFeedback.FireUpdate(); + if (!IsWarmingUpFeedback.BoolValue) + (CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume); + }; + display.IsCoolingDownFeedback.OutputChange += (o, a) => + { + IsCoolingDownFeedback.FireUpdate(); + }; + + } + } + var disp = DefaultDisplay as DisplayBase; if (disp != null) { diff --git a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs index f3988cb2..4b13145c 100644 --- a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs @@ -12,6 +12,8 @@ namespace PepperDash.Essentials { EssentialsConferenceRoomPropertiesConfig PropertiesConfig { get; } + bool ExcludeFromGlobalFunctions { get; } + void RunRouteAction(string routeKey); IHasScheduleAwareness ScheduleSource { get; } From c4752b2ac26c83c8efe34a19cb0a4dc5fa142497 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 21 Jul 2021 21:33:57 -0600 Subject: [PATCH 04/19] #753 EssentialsCombinedHuddleVtc1Room should be ready for testing --- .../Types/EssentialsCombinedHuddleVtc1Room.cs | 74 ++++++------------- .../EssentialsHuddlePanelAvFunctionsDriver.cs | 2 +- ...entialsHuddleVtc1PanelAvFunctionsDriver.cs | 2 +- 3 files changed, 24 insertions(+), 54 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs index de4b26ec..79f28aae 100644 --- a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs @@ -57,10 +57,11 @@ namespace PepperDash.Essentials { return () => { - var disp = DefaultDisplay as DisplayBase; + var displays = Displays.Where((d) => d is DisplayBase) as List; + var val = CurrentSourceInfo != null && CurrentSourceInfo.Type == eSourceListItemType.Route - && disp != null; + && displays.Count() > 0; //&& disp.PowerIsOnFeedback.BoolValue; return val; }; @@ -246,6 +247,8 @@ namespace PepperDash.Essentials DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls; + Displays = new List(); + Initialize(); } catch (Exception e) @@ -347,8 +350,8 @@ namespace PepperDash.Essentials { if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) { - if (!dispTwoWay.PowerIsOnFeedback.BoolValue) - CurrentSourceInfo = null; + //if (!dispTwoWay.PowerIsOnFeedback.BoolValue) + // CurrentSourceInfo = null; OnFeedback.FireUpdate(); } if (dispTwoWay.PowerIsOnFeedback.BoolValue) @@ -371,41 +374,6 @@ namespace PepperDash.Essentials } } - - var disp = DefaultDisplay as DisplayBase; - if (disp != null) - { - // Link power, warming, cooling to display - var dispTwoWay = disp as IHasPowerControlWithFeedback; - if (dispTwoWay != null) - { - dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) => - { - if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) - { - if (!dispTwoWay.PowerIsOnFeedback.BoolValue) - CurrentSourceInfo = null; - OnFeedback.FireUpdate(); - } - if (dispTwoWay.PowerIsOnFeedback.BoolValue) - { - SetDefaultLevels(); - } - }; - } - - disp.IsWarmingUpFeedback.OutputChange += (o, a) => - { - IsWarmingUpFeedback.FireUpdate(); - if (!IsWarmingUpFeedback.BoolValue) - (CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume); - }; - disp.IsCoolingDownFeedback.OutputChange += (o, a) => - { - IsCoolingDownFeedback.FireUpdate(); - }; - - } } private void SetSourceListKey() @@ -624,8 +592,8 @@ namespace PepperDash.Essentials if (string.IsNullOrEmpty(item.VolumeControlKey) || item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase)) volDev = DefaultVolumeControls; - else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) - volDev = DefaultDisplay as IBasicVolumeControls; + //else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) + // volDev = DefaultDisplay as IBasicVolumeControls; // Or a specific device, probably rarely used. else { @@ -717,14 +685,16 @@ namespace PepperDash.Essentials // if there is a $defaultAll on route, run two separate if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase)) { - // Going to assume a single-path route for now - var tempVideo = new SourceRouteListItem + foreach (var display in Displays) { - DestinationKey = "$defaultDisplay", - SourceKey = route.SourceKey, - Type = eRoutingSignalType.Video - }; - DoRoute(tempVideo); + var tempVideo = new SourceRouteListItem + { + DestinationKey = display.Key, + SourceKey = route.SourceKey, + Type = eRoutingSignalType.Video + }; + DoRoute(tempVideo); + } } else DoRoute(route); @@ -740,11 +710,11 @@ namespace PepperDash.Essentials IRoutingSink dest = null; if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase)) - dest = DefaultAudioDevice as IRoutingSinkNoSwitching; - else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) - dest = DefaultDisplay; + dest = DefaultAudioDevice as IRoutingSink; + //else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) + // dest = DefaultDisplay; else - dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching; + dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink; if (dest == null) { diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs index a0d5947c..1141b5fa 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs @@ -306,7 +306,7 @@ namespace PepperDash.Essentials TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () => { - if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IHasPowerControl) + if (CurrentRoom != null && CurrentRoom.DefaultDisplay != null && CurrentRoom.DefaultDisplay is IHasPowerControl) (CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle(); }); diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 6280f54e..6fb7a047 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -319,7 +319,7 @@ namespace PepperDash.Essentials TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () => { - if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IHasPowerControl) + if (CurrentRoom != null && CurrentRoom.DefaultDisplay != null && CurrentRoom.DefaultDisplay is IHasPowerControl) (CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle(); }); From bfa48091d95584220383d209efe68430b70e7a52 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 22 Jul 2021 12:44:13 -0600 Subject: [PATCH 05/19] #753 Adds methods to build new room type --- PepperDashEssentials/ControlSystem.cs | 7 +++++-- PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index ba5529d9..aafb5b1e 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -489,8 +489,11 @@ namespace PepperDash.Essentials { DeviceManager.AddDevice(room); - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId); - DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey)); + if (!(room is EssentialsCombinedHuddleVtc1Room)) + { + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId); + DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey)); + } Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); diff --git a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs index 5ec0565d..c5a6e949 100644 --- a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs +++ b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs @@ -39,6 +39,10 @@ namespace PepperDash.Essentials.Room.Config { return new EssentialsDualDisplayRoom(roomConfig); } + if (typeName == "combinedhuddlevtc1") + { + return new EssentialsCombinedHuddleVtc1Room(roomConfig); + } return typeName != "techroom" ? null : new EssentialsTechRoom(roomConfig); } From 2db397b474ea1eaf48d0b1d2aecba7e4b789261e Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 22 Jul 2021 12:46:27 -0600 Subject: [PATCH 06/19] #742 Adds step to post activation action to determine initial room combination scenario --- .../Room/Combining/EssentialsRoomCombiner.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs index 00c55d1c..a0284dc1 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs @@ -54,6 +54,15 @@ namespace PepperDash.Essentials.Core SetupPartitionStateProviders(); SetRooms(); + + if (isInAutoMode) + { + DetermineRoomCombinationScenario(); + } + else + { + SetRoomCombinationScenario(_propertiesConfig.defaultScenarioKey); + } }); } From 6542c062b9777b5de8ffe157cd0c74c4d7422019 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 23 Jul 2021 17:35:12 -0600 Subject: [PATCH 07/19] Working towards getting EssentialsTouchpanelController to switch rooms --- .../Room/Config/EssentialsRoomConfig.cs | 6 ++++ .../UI/EssentialsTouchpanelController.cs | 33 +++++++++++++++++++ ...entialsHuddleVtc1PanelAvFunctionsDriver.cs | 2 +- .../EssentialsRoomCombinerPropertiesConfig.cs | 2 +- 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs index c5a6e949..078f9bd5 100644 --- a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs +++ b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs @@ -187,6 +187,12 @@ namespace PepperDash.Essentials.Room.Config [JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")] public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; } + /// + /// Indicates if this room represents a combination of other rooms + /// + [JsonProperty("isRoomCombinationScenario")] + public bool IsRoomCombinationScenario { get; set; } + public EssentialsRoomPropertiesConfig() { LogoLight = new EssentialsLogoPropertiesConfig(); diff --git a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs index 7873bf42..b295cf95 100644 --- a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs +++ b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs @@ -16,6 +16,8 @@ namespace PepperDash.Essentials { public class EssentialsTouchpanelController : EssentialsDevice, IHasBasicTriListWithSmartObject { + private CrestronTouchpanelPropertiesConfig _propertiesConfig; + public BasicTriListWithSmartObject Panel { get; private set; } public PanelDriverBase PanelDriver { get; private set; } @@ -50,6 +52,7 @@ namespace PepperDash.Essentials public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id) : base(key, name) { + _propertiesConfig = props; Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating touchpanel hardware..."); type = type.ToLower(); @@ -124,8 +127,38 @@ namespace PepperDash.Essentials Panel.LoadSmartObjects(sgdName); Panel.SigChange += Panel_SigChange; + AddPostActivationAction(() => + { + // Check for IEssentialsRoomCombiner in DeviceManager and if found, subscribe to its event + + var roomCombiner = DeviceManager.AllDevices.FirstOrDefault((d) => d is IEssentialsRoomCombiner) as IEssentialsRoomCombiner; + + if (roomCombiner != null) + { + roomCombiner.RoomCombinationScenarioChanged += new EventHandler(roomCombiner_RoomCombinationScenarioChanged); + } + }); + } + void roomCombiner_RoomCombinationScenarioChanged(object sender, EventArgs e) + { + var roomCombiner = sender as IEssentialsRoomCombiner; + + string newRoomKey = null; + + if (roomCombiner.CurrentScenario.UiMap.ContainsKey(Key)) + { + newRoomKey = roomCombiner.CurrentScenario.UiMap[Key]; + } + else if (roomCombiner.CurrentScenario.UiMap.ContainsKey(_propertiesConfig.DefaultRoomKey)) + { + newRoomKey = roomCombiner.CurrentScenario.UiMap[_propertiesConfig.DefaultRoomKey]; + } + + // TODO: + } + public void LoadAndShowDriver(PanelDriverBase driver) { PanelDriver = driver; diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 6fb7a047..ffc6fec1 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -448,7 +448,7 @@ namespace PepperDash.Essentials // and the LastMeetingDismissed != this meeting var lastMeetingDismissed = meetings.FirstOrDefault(m => m.Id == LastMeetingDismissedId); - Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*", + Debug.Console(1, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*", CurrentRoom.OnFeedback.BoolValue, LastMeetingDismissedId, lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToShortTimeString() : ""); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs index 9d721584..6fb15042 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs @@ -30,7 +30,7 @@ namespace PepperDash.Essentials.Core /// /// The list of rooms keys that can be combined /// - [JsonProperty("roomMap")] + [JsonProperty("roomKeys")] public List RoomKeys {get; set;} /// From 7114e60c046f99f056abc306c4aaecf1d6d21234 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 30 Jul 2021 16:59:32 -0600 Subject: [PATCH 08/19] feat(RoomCombining): #742 Updates EssentialsTouchpanelController Will now switch room the TP is linked to based on room combination scenario --- .../UI/EssentialsTouchpanelController.cs | 293 ++++++++++-------- .../EssentialsPanelMainInterfaceDriver.cs | 33 +- .../UIDrivers/ScreenSaverController.cs | 17 +- .../Room/Combining/EssentialsRoomCombiner.cs | 14 +- .../Touchpanels/TriListExtensions.cs | 21 ++ 5 files changed, 248 insertions(+), 130 deletions(-) diff --git a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs index b295cf95..6d13614c 100644 --- a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs +++ b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs @@ -29,7 +29,14 @@ namespace PepperDash.Essentials : base(key, name) { Panel = tsw; - tsw.LoadSmartObjects(sgdPath); + + if (!string.IsNullOrEmpty(sgdPath)) + Panel.LoadSmartObjects(sgdPath); + else + Debug.Console(1, this, "No SGD file path defined"); + + + tsw.SigChange += Panel_SigChange; } @@ -39,7 +46,7 @@ namespace PepperDash.Essentials Panel = dge; if (!string.IsNullOrEmpty(sgdPath)) - dge.LoadSmartObjects(sgdPath); + Panel.LoadSmartObjects(sgdPath); else Debug.Console(1, this, "No SGD file path defined"); @@ -130,37 +137,191 @@ namespace PepperDash.Essentials AddPostActivationAction(() => { // Check for IEssentialsRoomCombiner in DeviceManager and if found, subscribe to its event - var roomCombiner = DeviceManager.AllDevices.FirstOrDefault((d) => d is IEssentialsRoomCombiner) as IEssentialsRoomCombiner; if (roomCombiner != null) { + // Subscribe to the even roomCombiner.RoomCombinationScenarioChanged += new EventHandler(roomCombiner_RoomCombinationScenarioChanged); + + // Connect to the initial roomKey + if (roomCombiner.CurrentScenario != null) + { + // Use the current scenario + DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); + } + else + { + // Current Scenario not yet set. Use default + SetupPanelDrivers(_propertiesConfig.DefaultRoomKey); + } + } + else + { + // No room combiner, use the default key + SetupPanelDrivers(_propertiesConfig.DefaultRoomKey); } }); - } void roomCombiner_RoomCombinationScenarioChanged(object sender, EventArgs e) { var roomCombiner = sender as IEssentialsRoomCombiner; + DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); + } + + /// + /// Determines the room key to use based on the scenario + /// + /// + void DetermineRoomKeyFromScenario(IRoomCombinationScenario scenario) + { string newRoomKey = null; - if (roomCombiner.CurrentScenario.UiMap.ContainsKey(Key)) + if (scenario.UiMap.ContainsKey(Key)) { - newRoomKey = roomCombiner.CurrentScenario.UiMap[Key]; + newRoomKey = scenario.UiMap[Key]; } - else if (roomCombiner.CurrentScenario.UiMap.ContainsKey(_propertiesConfig.DefaultRoomKey)) + else if (scenario.UiMap.ContainsKey(_propertiesConfig.DefaultRoomKey)) { - newRoomKey = roomCombiner.CurrentScenario.UiMap[_propertiesConfig.DefaultRoomKey]; + newRoomKey = scenario.UiMap[_propertiesConfig.DefaultRoomKey]; + } + + SetupPanelDrivers(newRoomKey); + } + + + /// + /// Sets up drivers and links them to the room specified + /// + /// key of room to link the drivers to + void SetupPanelDrivers(string roomKey) + { + // Clear out any existing actions + Panel.ClearAllSigActions(); + + Debug.Console(0, this, "Linking TP '{0}' to Room '{1}'", Key, roomKey); + + var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, _propertiesConfig); + // Then the sub drivers + + // spin up different room drivers depending on room type + var room = DeviceManager.GetDeviceForKey(roomKey); + if (room is IEssentialsHuddleSpaceRoom) + { + // Screen Saver Driver + + mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _propertiesConfig); + + // Header Driver + Debug.Console(0, this, "Adding header driver"); + mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _propertiesConfig); + + // AV Driver + Debug.Console(0, this, "Adding huddle space AV driver"); + var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, _propertiesConfig); + avDriver.DefaultRoomKey = roomKey; + mainDriver.AvDriver = avDriver; + avDriver.CurrentRoom = room as IEssentialsHuddleSpaceRoom; + + // Environment Driver + if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0) + { + Debug.Console(0, this, "Adding environment driver"); + mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _propertiesConfig); + + mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment); + } + + mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom); + + if (Panel is TswFt5ButtonSystem) + { + var tsw = Panel as TswFt5ButtonSystem; + // Wire up hard keys + tsw.Power.UserObject = new Action(b => { if (!b) avDriver.PowerButtonPressed(); }); + if (mainDriver.EnvironmentDriver != null) + tsw.Lights.UserObject = new Action(b => + { + if (!b) + { + mainDriver.EnvironmentDriver.Toggle(); + } + }); + tsw.Up.UserObject = new Action(avDriver.VolumeUpPress); + tsw.Down.UserObject = new Action(avDriver.VolumeDownPress); + } + } + else if (room is IEssentialsHuddleVtc1Room) + { + Debug.Console(0, this, "Adding huddle space VTC AV driver"); + + // Screen Saver Driver + mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _propertiesConfig); + + // Header Driver + mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _propertiesConfig); + + // AV Driver + var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, _propertiesConfig); + + var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(Panel, avDriver, + (room as IEssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver); + avDriver.SetVideoCodecDriver(codecDriver); + avDriver.DefaultRoomKey = roomKey; + mainDriver.AvDriver = avDriver; + avDriver.CurrentRoom = room as IEssentialsHuddleVtc1Room; + + // Environment Driver + if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0) + { + Debug.Console(0, this, "Adding environment driver"); + mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _propertiesConfig); + + mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment); + } + + mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom); + + + if (Panel is TswFt5ButtonSystem) + { + var tsw = Panel as TswFt5ButtonSystem; + // Wire up hard keys + tsw.Power.UserObject = new Action(b => { if (!b) avDriver.EndMeetingPress(); }); + if (mainDriver.EnvironmentDriver != null) + tsw.Lights.UserObject = new Action(b => + { + if (!b) + { + mainDriver.EnvironmentDriver.Toggle(); + } + }); + tsw.Up.UserObject = new Action(avDriver.VolumeUpPress); + tsw.Down.UserObject = new Action(avDriver.VolumeDownPress); + } + + LoadAndShowDriver(mainDriver); + } + else + { + Debug.Console(0, this, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", roomKey); } - // TODO: } public void LoadAndShowDriver(PanelDriverBase driver) { + if (PanelDriver != null) + { + var mainDriver = PanelDriver as EssentialsPanelMainInterfaceDriver; + if (mainDriver != null) + { + mainDriver.Dispose(); + } + } + PanelDriver = driver; driver.Show(); } @@ -171,7 +332,6 @@ namespace PepperDash.Essentials PanelDriver.BackButtonPressed(); } - void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) { // If the sig is transitioning on, mark it in case it was home button that transitioned it @@ -248,119 +408,6 @@ namespace PepperDash.Essentials var panelController = new EssentialsTouchpanelController(dc.Key, dc.Name, dc.Type, props, comm.IpIdInt); - panelController.AddPostActivationAction(() => - { - var mainDriver = new EssentialsPanelMainInterfaceDriver(panelController.Panel, props); - // Then the sub drivers - - // spin up different room drivers depending on room type - var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey); - if (room is IEssentialsHuddleSpaceRoom) - { - // Screen Saver Driver - mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, props); - - // Header Driver - Debug.Console(0, panelController, "Adding header driver"); - mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props); - - // AV Driver - Debug.Console(0, panelController, "Adding huddle space AV driver"); - var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props); - avDriver.DefaultRoomKey = props.DefaultRoomKey; - mainDriver.AvDriver = avDriver; - avDriver.CurrentRoom = room as IEssentialsHuddleSpaceRoom; - - // Environment Driver - if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0) - { - Debug.Console(0, panelController, "Adding environment driver"); - mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props); - - mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment); - } - - mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom); - - panelController.LoadAndShowDriver(mainDriver); // This is a little convoluted. - - if (panelController.Panel is TswFt5ButtonSystem) - { - var tsw = panelController.Panel as TswFt5ButtonSystem; - // Wire up hard keys - tsw.Power.UserObject = new Action(b => { if (!b) avDriver.PowerButtonPressed(); }); - //tsw.Home.UserObject = new Action(b => { if (!b) HomePressed(); }); - if (mainDriver.EnvironmentDriver != null) - tsw.Lights.UserObject = new Action(b => - { - if (!b) - { - //mainDriver.AvDriver.PopupInterlock.ShowInterlockedWithToggle(mainDriver.EnvironmentDriver.BackgroundSubpageJoin); - mainDriver.EnvironmentDriver.Toggle(); - } - }); - tsw.Up.UserObject = new Action(avDriver.VolumeUpPress); - tsw.Down.UserObject = new Action(avDriver.VolumeDownPress); - } - } - else if (room is IEssentialsHuddleVtc1Room) - { - Debug.Console(0, panelController, "Adding huddle space VTC AV driver"); - - // Screen Saver Driver - mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, props); - - // Header Driver - mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props); - - // AV Driver - var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, props); - - var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(panelController.Panel, avDriver, - (room as IEssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver); - avDriver.SetVideoCodecDriver(codecDriver); - avDriver.DefaultRoomKey = props.DefaultRoomKey; - mainDriver.AvDriver = avDriver; - avDriver.CurrentRoom = room as IEssentialsHuddleVtc1Room; - - // Environment Driver - if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0) - { - Debug.Console(0, panelController, "Adding environment driver"); - mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props); - - mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment); - } - - mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom); - - panelController.LoadAndShowDriver(mainDriver); // This is a little convoluted. - - if (panelController.Panel is TswFt5ButtonSystem) - { - var tsw = panelController.Panel as TswFt5ButtonSystem; - // Wire up hard keys - tsw.Power.UserObject = new Action(b => { if (!b) avDriver.EndMeetingPress(); }); - //tsw.Home.UserObject = new Action(b => { if (!b) HomePressed(); }); - if (mainDriver.EnvironmentDriver != null) - tsw.Lights.UserObject = new Action(b => - { - if (!b) - { - //mainDriver.AvDriver.PopupInterlock.ShowInterlockedWithToggle(mainDriver.EnvironmentDriver.BackgroundSubpageJoin); - mainDriver.EnvironmentDriver.Toggle(); - } - }); - tsw.Up.UserObject = new Action(avDriver.VolumeUpPress); - tsw.Down.UserObject = new Action(avDriver.VolumeDownPress); - } - } - else - { - Debug.Console(0, panelController, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", props.DefaultRoomKey); - } - }); - return panelController; } } diff --git a/PepperDashEssentials/UIDrivers/Essentials/EssentialsPanelMainInterfaceDriver.cs b/PepperDashEssentials/UIDrivers/Essentials/EssentialsPanelMainInterfaceDriver.cs index 9b92fc41..2b787063 100644 --- a/PepperDashEssentials/UIDrivers/Essentials/EssentialsPanelMainInterfaceDriver.cs +++ b/PepperDashEssentials/UIDrivers/Essentials/EssentialsPanelMainInterfaceDriver.cs @@ -11,7 +11,7 @@ namespace PepperDash.Essentials /// /// /// - public class EssentialsPanelMainInterfaceDriver : PanelDriverBase, IHasScreenSaverController + public class EssentialsPanelMainInterfaceDriver : PanelDriverBase, IHasScreenSaverController, IDisposable { CTimer InactivityTimer; @@ -69,6 +69,35 @@ namespace PepperDash.Essentials } } + #region IDisposable Members + + public void Dispose() + { + var avDriver = AvDriver as PanelDriverBase; + if (avDriver != null) + { + avDriver.Hide(); + } + if (ScreenSaverController != null) + { + ScreenSaverController.Dispose(); + } + if (HeaderDriver != null) + { + HeaderDriver.Hide(); + } + if (EnvironmentDriver != null) + { + EnvironmentDriver.Hide(); + } + if (CurrentChildDriver != null) + { + CurrentChildDriver.Hide(); + } + } + + #endregion + void ExtenderTouchDetectionReservedSigs_DeviceExtenderSigChange(Crestron.SimplSharpPro.DeviceExtender currentDeviceExtender, Crestron.SimplSharpPro.SigEventArgs args) { @@ -130,7 +159,7 @@ namespace PepperDash.Essentials if(CurrentChildDriver != null) CurrentChildDriver.BackButtonPressed(); } - } + } public interface IHasScreenSaverController { diff --git a/PepperDashEssentials/UIDrivers/ScreenSaverController.cs b/PepperDashEssentials/UIDrivers/ScreenSaverController.cs index e6d60d5b..afced26e 100644 --- a/PepperDashEssentials/UIDrivers/ScreenSaverController.cs +++ b/PepperDashEssentials/UIDrivers/ScreenSaverController.cs @@ -12,7 +12,7 @@ namespace PepperDash.Essentials /// /// Driver responsible for controlling the screenshaver showing the client logo, MC connection information and QR Code. Moves the elements around to prevent screen burn in /// - public class ScreenSaverController : PanelDriverBase + public class ScreenSaverController : PanelDriverBase, IDisposable { /// @@ -65,7 +65,7 @@ namespace PepperDash.Essentials public override void Hide() { - Debug.Console(1, "Hiding ScreenSaverController"); + Debug.Console(2, "Hiding ScreenSaverController"); if (PositionTimer != null) { @@ -117,7 +117,7 @@ namespace PepperDash.Essentials CurrentPositionIndex = 0; } - Debug.Console(1, "ScreenSaver Position Timer Expired: Setting new position: {0}", CurrentPositionIndex); + //Debug.Console(2, "ScreenSaver Position Timer Expired: Setting new position: {0}", CurrentPositionIndex); } // @@ -129,9 +129,18 @@ namespace PepperDash.Essentials void ClearAllPositions() { - Debug.Console(1, "Hiding all screensaver positions"); + Debug.Console(2, "Hiding all screensaver positions"); PositionInterlock.HideAndClear(); } + + #region IDisposable Members + + public void Dispose() + { + Hide(); + } + + #endregion } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs index a0284dc1..d9886e70 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs @@ -167,7 +167,7 @@ namespace PepperDash.Essentials.Core { return _currentScenario; } - set + private set { if (value != _currentScenario) { @@ -227,9 +227,11 @@ namespace PepperDash.Essentials.Core // Get the scenario var scenario = RoomCombinationScenarios.FirstOrDefault((s) => s.Key.Equals(scenarioKey)); + // Set the parition states from the scenario manually if (scenario != null) { + Debug.Console(0, this, "Manually setting scenario to '{0}'", scenario.Key); foreach (var partitionState in scenario.PartitionStates) { var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey)); @@ -238,15 +240,25 @@ namespace PepperDash.Essentials.Core { if (partitionState.PartitionPresent) { + Debug.Console(0, this, "Manually setting state to Present for: '{0}'", partition.Key); partition.SetPartitionStatePresent(); } else { + Debug.Console(0, this, "Manually setting state to Not Present for: '{0}'", partition.Key); partition.SetPartitionStateNotPresent(); } } + else + { + Debug.Console(1, this, "Unable to find partition with key: '{0}'", partitionState.PartitionKey); + } } } + else + { + Debug.Console(1, this, "Unable to find scenario with key: '{0}'", scenarioKey); + } } #endregion diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/TriListExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/TriListExtensions.cs index d9cadb24..bfbb73f0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/TriListExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/TriListExtensions.cs @@ -206,6 +206,27 @@ namespace PepperDash.Essentials.Core return ClearSigAction(tl.StringOutput[sigNum]) as StringOutputSig; } + /// + /// Clears all actions on all sigs + /// + public static void ClearAllSigActions(this BasicTriList t1) + { + foreach (var sig in t1.BooleanOutput) + { + ClearSigAction(sig); + } + + foreach (var sig in t1.UShortOutput) + { + ClearSigAction(sig); + } + + foreach (var sig in t1.StringOutput) + { + ClearSigAction(sig); + } + } + /// /// Helper method to set the value of a bool Sig on TriList /// From 77672237e63b325b13e0ded78ef6c84733bcc664 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 30 Jul 2021 17:27:38 -0600 Subject: [PATCH 09/19] Adds some debug comments to assist in debugging --- PepperDashEssentials/UIDrivers/ScreenSaverController.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/PepperDashEssentials/UIDrivers/ScreenSaverController.cs b/PepperDashEssentials/UIDrivers/ScreenSaverController.cs index afced26e..49357868 100644 --- a/PepperDashEssentials/UIDrivers/ScreenSaverController.cs +++ b/PepperDashEssentials/UIDrivers/ScreenSaverController.cs @@ -51,6 +51,8 @@ namespace PepperDash.Essentials public override void Show() { + Debug.Console(2, "Showing ScreenSaverController"); + if (_parent.AvDriver != null) { _parent.AvDriver.PopupInterlock.ShowInterlocked(UIBoolJoin.MCScreenSaverVisible); @@ -86,6 +88,8 @@ namespace PepperDash.Essentials void StartPositionTimer() { + Debug.Console(2, "Starting Position Timer"); + if (PositionTimer == null) { PositionTimer = new CTimer((o) => PositionTimerExpired(), PositionTimeoutMs); @@ -117,7 +121,7 @@ namespace PepperDash.Essentials CurrentPositionIndex = 0; } - //Debug.Console(2, "ScreenSaver Position Timer Expired: Setting new position: {0}", CurrentPositionIndex); + Debug.Console(2, "ScreenSaver Position Timer Expired: Setting new position: {0}", CurrentPositionIndex); } // From 0e41cafdadef2826ec49069aa2c151810744f689 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 2 Aug 2021 14:22:31 -0600 Subject: [PATCH 10/19] Adds some debug comments to assist in debugging --- .../UI/EssentialsTouchpanelController.cs | 2 ++ .../UIDrivers/ScreenSaverController.cs | 14 ++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs index 0c4e3b88..becba34c 100644 --- a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs +++ b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs @@ -71,6 +71,8 @@ namespace PepperDash.Essentials app.ParameterProjectName.Value = props.ProjectName; Panel = app; } + else if (type == "xpanel") + Panel = new XpanelForSmartGraphics(id, Global.ControlSystem); else if (type == "tsw550") Panel = new Tsw550(id, Global.ControlSystem); else if (type == "tsw552") diff --git a/PepperDashEssentials/UIDrivers/ScreenSaverController.cs b/PepperDashEssentials/UIDrivers/ScreenSaverController.cs index 49357868..0f75e2a2 100644 --- a/PepperDashEssentials/UIDrivers/ScreenSaverController.cs +++ b/PepperDashEssentials/UIDrivers/ScreenSaverController.cs @@ -42,7 +42,7 @@ namespace PepperDash.Essentials PositionInterlock = new JoinedSigInterlock(parent.TriList); - var cmdName = String.Format("shwscrsvr-{0}", parent.TriList.ID); + var cmdName = String.Format("shwscrsvr-{0:X2}", parent.TriList.ID); CrestronConsole.AddNewConsoleCommand((o) => Show(), cmdName, "Shows Panel Screensaver", ConsoleAccessLevelEnum.AccessOperator); @@ -51,7 +51,7 @@ namespace PepperDash.Essentials public override void Show() { - Debug.Console(2, "Showing ScreenSaverController"); + Debug.Console(2, "Showing ScreenSaverController: {0:X2}", TriList.ID); if (_parent.AvDriver != null) { @@ -67,10 +67,11 @@ namespace PepperDash.Essentials public override void Hide() { - Debug.Console(2, "Hiding ScreenSaverController"); + Debug.Console(2, "Hiding ScreenSaverController: {0:X2}", TriList.ID); if (PositionTimer != null) { + Debug.Console(2, "Stopping PositionTimer: {0:X2}", TriList.ID); PositionTimer.Stop(); PositionTimer.Dispose(); PositionTimer = null; @@ -88,7 +89,7 @@ namespace PepperDash.Essentials void StartPositionTimer() { - Debug.Console(2, "Starting Position Timer"); + Debug.Console(2, "Starting Position Timer: {0:X2}", TriList.ID); if (PositionTimer == null) { @@ -121,7 +122,7 @@ namespace PepperDash.Essentials CurrentPositionIndex = 0; } - Debug.Console(2, "ScreenSaver Position Timer Expired: Setting new position: {0}", CurrentPositionIndex); + Debug.Console(2, "ScreenSaver Position Timer Expired: Setting new position: {0} ID: {1:X2}", CurrentPositionIndex, TriList.ID); } // @@ -133,7 +134,8 @@ namespace PepperDash.Essentials void ClearAllPositions() { - Debug.Console(2, "Hiding all screensaver positions"); + Debug.Console(2, "Hiding all screensaver positions: {0:X2}", TriList.ID); + PositionInterlock.HideAndClear(); } From 5c3e1ca9151d23592ea65ba2d18c4e34c9c44874 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 3 Aug 2021 14:52:26 -0600 Subject: [PATCH 11/19] Updates IMobileControl to use IEssentialsRoom instead of EssentialsRoomBase again --- PepperDashEssentials/ControlSystem.cs | 8 ++++---- .../DeviceTypeInterfaces/IMobileControl.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index f3fcafab..aafb5b1e 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -483,7 +483,7 @@ namespace PepperDash.Essentials Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); - CreateMobileControlBridge(room as EssentialsRoomBase); + CreateMobileControlBridge(room); } else if (room is IEssentialsHuddleVtc1Room) { @@ -497,7 +497,7 @@ namespace PepperDash.Essentials Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); - CreateMobileControlBridge(room as EssentialsRoomBase); + CreateMobileControlBridge(room); } else if (room is EssentialsTechRoom) { @@ -509,7 +509,7 @@ namespace PepperDash.Essentials Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge"); - CreateMobileControlBridge(room as EssentialsRoomBase); + CreateMobileControlBridge(room); } else { @@ -530,7 +530,7 @@ namespace PepperDash.Essentials } - private static void CreateMobileControlBridge(EssentialsRoomBase room) + private static void CreateMobileControlBridge(IEssentialsRoom room) { var mobileControl = GetMobileControlDevice(); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs index c87e7865..a2dda43a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs @@ -8,7 +8,7 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces /// public interface IMobileControl : IKeyed { - void CreateMobileControlRoomBridge(EssentialsRoomBase room, IMobileControl parent); + void CreateMobileControlRoomBridge(IEssentialsRoom room, IMobileControl parent); void LinkSystemMonitorToAppServer(); } From 0867d08c5aa1058b4030caa2e6a4627303cbc72c Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 4 Aug 2021 15:13:35 -0600 Subject: [PATCH 12/19] fix(MockVC): various fixes for local testing update MockVC and EssentialsVideoCodecUiDriver updates to Cisco classes to address some exceptions at startup with EssentialsVideoCodecUiDriver --- .../Properties/ControlSystem.cfg | 4 +-- ...entialsHuddleVtc1PanelAvFunctionsDriver.cs | 8 ++--- .../VC/EssentialsVideoCodecUiDriver.cs | 19 ++++++---- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 35 +++++++++++-------- .../VideoCodec/CiscoCodec/xStatus.cs | 1 + .../VideoCodec/MockVC/MockVC.cs | 19 ++++++++-- .../MockVC/MockVcPropertiesConfig.cs | 6 ++++ 7 files changed, 62 insertions(+), 30 deletions(-) diff --git a/PepperDashEssentials/Properties/ControlSystem.cfg b/PepperDashEssentials/Properties/ControlSystem.cfg index d2c3b2c7..384bf949 100644 --- a/PepperDashEssentials/Properties/ControlSystem.cfg +++ b/PepperDashEssentials/Properties/ControlSystem.cfg @@ -1,7 +1,7 @@  - 192.168.10.1 -
auto 192.168.10.1
+ Test RMC3 +
auto 192.168.1.40;username crestron
Program01 Internal Flash
\ No newline at end of file diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index e9dc824b..d2978c44 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -448,10 +448,10 @@ namespace PepperDash.Essentials // and the LastMeetingDismissed != this meeting var lastMeetingDismissed = meetings.FirstOrDefault(m => m.Id == LastMeetingDismissedId); - Debug.Console(1, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*", - CurrentRoom.OnFeedback.BoolValue, - LastMeetingDismissedId, - lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToShortTimeString() : ""); + //Debug.Console(1, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*", + // CurrentRoom.OnFeedback.BoolValue, + // LastMeetingDismissedId, + // lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToShortTimeString() : ""); var meeting = meetings.LastOrDefault(m => m.Joinable); if (CurrentRoom.OnFeedback.BoolValue diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index e95ab5e5..9159381e 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -123,12 +123,6 @@ namespace PepperDash.Essentials.UIDrivers.VC codec.CallStatusChange += new EventHandler(Codec_CallStatusChange); - // If the codec is ready, then get the values we want, otherwise wait - if (Codec.IsReady) - Codec_IsReady(); - else - codec.IsReadyChange += (o, a) => Codec_IsReady(); - //InCall = new BoolFeedback(() => false); LocalPrivacyIsMuted = new BoolFeedback(() => false); @@ -199,6 +193,14 @@ namespace PepperDash.Essentials.UIDrivers.VC triList.SetSigHeldAction(UIBoolJoin.VCDirectoryBackspacePress, 500, StartSearchBackspaceRepeat, StopSearchBackspaceRepeat, SearchKeypadBackspacePress); + // If the codec is ready, then get the values we want, otherwise wait + if (Codec.IsReady) + Codec_IsReady(); + else + codec.IsReadyChange += (o, a) => Codec_IsReady(); + + + } catch (Exception e) { @@ -518,7 +520,6 @@ namespace PepperDash.Essentials.UIDrivers.VC VCControlsInterlock.StatusChanged += new EventHandler(VCControlsInterlock_StatusChanged); - var codecOffCameras = Codec as IHasCameraOff; var supportsCameraOffMode = Codec.SupportsCameraOff; @@ -529,6 +530,7 @@ namespace PepperDash.Essentials.UIDrivers.VC if (codecAutoCameras != null && supportsAutoCameraMode) { + CameraModeList.SetItemButtonAction(1,(b) => codecAutoCameras.CameraAutoModeOn()); TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 1 Visible"].BoolValue = true; codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 1 Selected"]); @@ -558,6 +560,7 @@ namespace PepperDash.Essentials.UIDrivers.VC } }; + } // Manual button always visible @@ -569,6 +572,7 @@ namespace PepperDash.Essentials.UIDrivers.VC if (codecOffCameras != null && supportsCameraOffMode) { + TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 3 Visible"].BoolValue = true; codecOffCameras.CameraIsOffFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 3 Selected"]); CameraModeList.SetItemButtonAction(3, (b) => codecOffCameras.CameraOff()); @@ -596,6 +600,7 @@ namespace PepperDash.Essentials.UIDrivers.VC } }; + } } 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 bce321b9..660ec0f1 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 @@ -352,8 +352,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco CallHistory = new CodecCallHistory(); - - if (props.Favorites != null) + if (props.Favorites != null) { CallFavorites = new CodecCallFavorites(); CallFavorites.Favorites = props.Favorites; @@ -369,9 +368,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco CodecSchedule = new CodecScheduleAwareness(); - //Set Feedback Actions - SetFeedbackActions(); - CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this); HdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video, @@ -406,6 +402,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco BrandingEnabled = props.UiBranding.Enable; _brandingUrl = props.UiBranding.BrandingUrl; + + //Set Feedback Actions + SetFeedbackActions(); } private void SetFeedbackActions() @@ -429,11 +428,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } catch (Exception ex) { - Debug.Console(0, this, "Error setting MainVideuMute Action: {0}", ex); + Debug.Console(0, this, "Error setting MainVideoMute Action: {0}", ex); if (ex.InnerException != null) { - Debug.Console(0, this, "Error setting MainVideuMute Action: {0}", ex); + Debug.Console(0, this, "Error setting MainVideoMute Action: {0}", ex); } } } @@ -1879,17 +1878,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { get { - if (CodecStatus.Status.SIP != null && CodecStatus.Status.SIP.AlternateURI.Primary.URI.Value != null) + try { - return CodecStatus.Status.SIP.AlternateURI.Primary.URI.Value; + if (CodecStatus.Status.SIP != null && CodecStatus.Status.SIP.AlternateURI != null) + { + return CodecStatus.Status.SIP.AlternateURI.Primary.URI.Value; + } + else if (CodecStatus.Status.UserInterface != null && + CodecStatus.Status.UserInterface.ContactInfo != null && CodecStatus.Status.UserInterface.ContactInfo != null) + { + return CodecStatus.Status.UserInterface.ContactInfo.ContactMethod[0].Number.Value; + } + else + return string.Empty; } - else if (CodecStatus.Status.UserInterface != null && - CodecStatus.Status.UserInterface.ContactInfo.ContactMethod[0].Number.Value != null) + catch (Exception e) { - return CodecStatus.Status.UserInterface.ContactInfo.ContactMethod[0].Number.Value; - } - else + Debug.Console(2, "Error getting SipUri: {0}", e); return string.Empty; + } } } 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 8184289e..c1cd92cf 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 @@ -327,6 +327,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public SpeakerTrack() { Status = new Status2(); + Availability = new Availability(); } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs index ca199957..5d701f7b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs @@ -416,8 +416,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec m.MinutesBeforeMeeting = 5; m.Id = i.ToString(); m.Organizer = "Employee " + 1; - m.StartTime = DateTime.Now.AddMinutes(6).AddHours(i); - m.EndTime = DateTime.Now.AddHours(i).AddMinutes(16); + m.StartTime = DateTime.Now.AddMinutes(5).AddHours(i); + m.EndTime = DateTime.Now.AddHours(i).AddMinutes(50); m.Title = "Meeting " + i; m.Calls.Add(new Call() { Number = i + "meeting@fake.com"}); _CodecSchedule.Meetings.Add(m); @@ -583,6 +583,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec CameraAutoModeIsOnFeedback = new BoolFeedback(() => _CameraAutoModeIsOn); + SupportsCameraAutoMode = true; + CameraAutoModeIsOnFeedback.FireUpdate(); DeviceManager.AddDevice(internalCamera); @@ -590,7 +592,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec NearEndPresets = new List(15); // Fix the capacity to emulate Cisco - NearEndPresets = PropertiesConfig.Presets; + if (PropertiesConfig.Presets != null && PropertiesConfig.Presets.Count > 0) + { + NearEndPresets = PropertiesConfig.Presets; + } + else + { + for (int i = 1; i <= NearEndPresets.Capacity; i++) + { + var label = string.Format("Near End Preset {0}", i); + NearEndPresets.Add(new CodecRoomPreset(i, label, true, false)); + } + } FarEndRoomPresets = new List(15); // Fix the capacity to emulate Cisco diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVcPropertiesConfig.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVcPropertiesConfig.cs index 6a790af6..d294aff1 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVcPropertiesConfig.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVcPropertiesConfig.cs @@ -18,5 +18,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec [JsonProperty("presets")] public List Presets { get; set; } + + public MockVcPropertiesConfig() + { + Favorites = new List(); + Presets = new List(); + } } } \ No newline at end of file From 397a5b1794e68c00f25e4902f65ae3413ea46382 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 5 Aug 2021 17:28:49 -0600 Subject: [PATCH 13/19] fix(CiscoSparkCodec): Solves exception when in SipUri getter --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 660ec0f1..ae740dbf 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 @@ -1880,17 +1880,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { try { - if (CodecStatus.Status.SIP != null && CodecStatus.Status.SIP.AlternateURI != null) + if (CodecStatus.Status.SIP != null && !string.IsNullOrEmpty(CodecStatus.Status.SIP.AlternateURI.Primary.URI.Value)) { return CodecStatus.Status.SIP.AlternateURI.Primary.URI.Value; } else if (CodecStatus.Status.UserInterface != null && - CodecStatus.Status.UserInterface.ContactInfo != null && CodecStatus.Status.UserInterface.ContactInfo != null) + CodecStatus.Status.UserInterface.ContactInfo != null && CodecStatus.Status.UserInterface.ContactInfo.ContactMethod != null) { return CodecStatus.Status.UserInterface.ContactInfo.ContactMethod[0].Number.Value; } else + { return string.Empty; + } } catch (Exception e) { From 1bf828b8a9c0c658780bdc0012ac7dd8bb994e9a Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 12 Aug 2021 09:36:03 -0600 Subject: [PATCH 14/19] Updates feedback funcs for combined room type --- .../Types/EssentialsCombinedHuddleVtc1Room.cs | 41 +++---------------- devjson commands.json | 3 ++ 2 files changed, 8 insertions(+), 36 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs index 79f28aae..9dec21f2 100644 --- a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs @@ -57,11 +57,12 @@ namespace PepperDash.Essentials { return () => { - var displays = Displays.Where((d) => d is DisplayBase) as List; + + var displays = Displays.OfType().ToList(); var val = CurrentSourceInfo != null && CurrentSourceInfo.Type == eSourceListItemType.Route - && displays.Count() > 0; + && displays.Count > 0; //&& disp.PowerIsOnFeedback.BoolValue; return val; }; @@ -74,23 +75,7 @@ namespace PepperDash.Essentials { get { - return () => - { - var displays = Displays.Where((d) => d is TwoWayDisplayBase) as List; - if (displays != null) - { - var warmingDisplays = displays.Where((d) => d.IsWarmingUpFeedback.BoolValue); - - if (warmingDisplays.Count() > 0) - { - return true; - } - else - return false; - } - else - return false; - }; + return () => Displays.OfType().Any((d) => d.IsWarmingUpFeedback.BoolValue); } } /// @@ -100,23 +85,7 @@ namespace PepperDash.Essentials { get { - return () => - { - var displays = Displays.Where((d) => d is TwoWayDisplayBase) as List; - if (displays != null) - { - var coolingDisplays = displays.Where((d) => d.IsCoolingDownFeedback.BoolValue); - - if (coolingDisplays.Count() > 0) - { - return true; - } - else - return false; - } - else - return false; - }; + return () => Displays.OfType().Any((d) => d.IsCoolingDownFeedback.BoolValue); } } diff --git a/devjson commands.json b/devjson commands.json index 62e675d1..c7ed7291 100644 --- a/devjson commands.json +++ b/devjson commands.json @@ -42,3 +42,6 @@ devjson:2 {"deviceKey":"display01Comm-com", "methodName":"SendText", "params": [ devjson:10 {"deviceKey":"dmLink-ssh", "methodName":"Connect", "params": []} +devjson:2 {"deviceKey":"roomCombiner", "methodName":"SetRoomCombinationScenario", "params": ["combined"]} + +devjson:2 {"deviceKey":"roomCombiner", "methodName":"SetRoomCombinationScenario", "params": ["divided"]} \ No newline at end of file From 5c02d72ed1b27a45a71edc3bf8581fbd71d9f715 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 17 Aug 2021 16:38:51 -0600 Subject: [PATCH 15/19] fix(essentials): Allows SubpageReferenceListSourceItem to deregister from room's CurrentSourceInfoChange event on Clear() --- PepperDashEssentials/UI/SubpageReferenceListSourceItem.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/PepperDashEssentials/UI/SubpageReferenceListSourceItem.cs b/PepperDashEssentials/UI/SubpageReferenceListSourceItem.cs index 3e1869cc..27409007 100644 --- a/PepperDashEssentials/UI/SubpageReferenceListSourceItem.cs +++ b/PepperDashEssentials/UI/SubpageReferenceListSourceItem.cs @@ -14,6 +14,8 @@ namespace PepperDash.Essentials { public SourceListItem SourceItem { get; private set; } + private IHasCurrentSourceInfoChange _room; + public SubpageReferenceListSourceItem(uint index, SubpageReferenceList owner, SourceListItem sourceItem, Action routeAction) : base(index, owner) @@ -25,6 +27,7 @@ namespace PepperDash.Essentials public void RegisterForSourceChange(IHasCurrentSourceInfoChange room) { + _room = room; room.CurrentSourceChange -= room_CurrentSourceInfoChange; room.CurrentSourceChange += room_CurrentSourceInfoChange; } @@ -44,6 +47,9 @@ namespace PepperDash.Essentials { Owner.BoolInputSig(Index, 1).UserObject = null; Owner.StringInputSig(Index, 1).StringValue = ""; + + if(_room != null) + _room.CurrentSourceChange -= room_CurrentSourceInfoChange; } /// From 12e8dca47e8b09ef806e39725bdce24f7edca3ef Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 17 Aug 2021 16:41:23 -0600 Subject: [PATCH 16/19] fix(essentials): #792 refactors logic to show/hide SelectASourceVisible subpage --- .../EssentialsHuddlePanelAvFunctionsDriver.cs | 1 + ...entialsHuddleVtc1PanelAvFunctionsDriver.cs | 47 +++++++++++++++---- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs index 1141b5fa..e58172de 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs @@ -918,6 +918,7 @@ namespace PepperDash.Essentials TriList.BooleanInput[StartPageVisibleJoin].BoolValue = true; TriList.BooleanInput[UIBoolJoin.VolumeSingleMute1Visible].BoolValue = false; TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = false; + TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; } } diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 0e132ce6..5852526e 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -633,7 +633,10 @@ namespace PepperDash.Essentials var callMode = CurrentMode == UiDisplayMode.Call; TriList.SetBool(StartPageVisibleJoin, startMode ? true : false); + TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, presentationMode ? true : false); + if (!presentationMode) + TriList.SetBool(UIBoolJoin.SelectASourceVisible, false); CallButtonSig.BoolValue = callMode && CurrentRoom.ShutdownType == eShutdownType.None; @@ -674,19 +677,19 @@ namespace PepperDash.Essentials // Run default source when room is off and share is pressed if (!CurrentRoom.OnFeedback.BoolValue) { - if (!CurrentRoom.OnFeedback.BoolValue) - { - // If there's no default, show UI elements - if (!(CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute()) - TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); - } - } + // If there's no default, show UI elements + if (!(CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute()) + TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); + } else // room is on show what's active or select a source if nothing is yet active { - if(CurrentRoom.CurrentSourceInfo == null || CurrentRoom.CurrentSourceInfoKey == CurrentRoom.DefaultCodecRouteString) + if(CurrentRoom.CurrentSourceInfo == null || (CurrentRoom.VideoCodec != null && CurrentRoom.CurrentSourceInfo.SourceDevice.Key == CurrentRoom.VideoCodec.OsdSource.Key)) TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); else if (CurrentSourcePageManager != null) + { + TriList.SetBool(UIBoolJoin.SelectASourceVisible, false); CurrentSourcePageManager.Show(); + } } CurrentMode = UiDisplayMode.Presentation; SetupSourceList(); @@ -1131,6 +1134,30 @@ namespace PepperDash.Essentials /// void CurrentRoom_CurrentSingleSourceChange(SourceListItem info, ChangeType type) { + Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange"); + + // Show the Select a source subpage + if (TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue) + { + Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange SourceStagingBarVisisble: true"); + + if (_CurrentRoom.CurrentSourceInfo == null || (_CurrentRoom.VideoCodec != null && _CurrentRoom.CurrentSourceInfo.SourceDevice.Key == _CurrentRoom.VideoCodec.OsdSource.Key)) + { + Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange Showing SelectASourceVisible"); + TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); + } + else + { + TriList.SetBool(UIBoolJoin.SelectASourceVisible, false); + Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange Hiding SelectASourceVisible"); + } + } + else + { + Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange Hiding SelectASourceVisible"); + TriList.SetBool(UIBoolJoin.SelectASourceVisible, false); + } + if (_CurrentRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue && _CurrentRoom.CurrentSourceInfo != null) TriList.StringInput[UIStringJoin.CallSharedSourceNameText].StringValue = _CurrentRoom.CurrentSourceInfo.PreferredName; } @@ -1228,12 +1255,12 @@ namespace PepperDash.Essentials var value = _CurrentRoom.OnFeedback.BoolValue; TriList.BooleanInput[UIBoolJoin.RoomIsOn].BoolValue = value; - TriList.BooleanInput[StartPageVisibleJoin].BoolValue = !value; + //TriList.BooleanInput[StartPageVisibleJoin].BoolValue = !value; if (value) //ON { SetupActivityFooterWhenRoomOn(); - TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; + //TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; TriList.BooleanInput[UIBoolJoin.VolumeDualMute1Visible].BoolValue = true; } From 26bf7d8f736590a3326ba0d2b0e89e946c32fe63 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 17 Aug 2021 17:58:32 -0600 Subject: [PATCH 17/19] feat(essentials): #793 Implements IHasDirectoryHistoryStack on CiscoSparkCodec --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index ae740dbf..893d9b0d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -24,9 +24,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { enum eCommandType { SessionStart, SessionEnd, Command, GetStatus, GetConfiguration }; public enum eExternalSourceType {camera, desktop, document_camera, mediaplayer, PC, whiteboard, other} - public enum eExternalSourceMode {Ready, NotReady, Hidden, Error} + public enum eExternalSourceMode {Ready, NotReady, Hidden, Error} - public class CiscoSparkCodec : VideoCodecBase, IHasCallHistory, IHasCallFavorites, IHasDirectory, + public class CiscoSparkCodec : VideoCodecBase, IHasCallHistory, IHasCallFavorites, IHasDirectoryHistoryStack, IHasScheduleAwareness, IOccupancyStatusProvider, IHasCodecLayouts, IHasCodecSelfView, ICommunicationMonitor, IRouting, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets, IHasExternalSourceSwitching, IHasBranding, IHasCameraOff, IHasCameraMute { @@ -106,6 +106,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// public CodecDirectory DirectoryRoot { get; private set; } + + private CodecDirectory _currentDirectoryResult; + /// /// Represents the current state of the directory and is computed on get /// @@ -113,10 +116,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { get { - if (DirectoryBrowseHistory.Count > 0) - return DirectoryBrowseHistory[DirectoryBrowseHistory.Count - 1]; - else - return DirectoryRoot; + return _currentDirectoryResult; + } + private set + { + _currentDirectoryResult = value; + + CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); + + OnDirectoryResultReturned(_currentDirectoryResult); } } @@ -127,6 +135,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// public List DirectoryBrowseHistory { get; private set; } + public Stack DirectoryBrowseHistoryStack { get; private set; } + public CodecScheduleAwareness CodecSchedule { get; private set; } /// @@ -362,9 +372,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco DirectoryBrowseHistory = new List(); - CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => DirectoryBrowseHistory.Count > 0); + DirectoryBrowseHistoryStack = new Stack(); - CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); + CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => CurrentDirectoryResult != DirectoryRoot); CodecSchedule = new CodecScheduleAwareness(); @@ -1024,6 +1034,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco PhonebookSyncState.PhonebookRootEntriesReceived(); + CurrentDirectoryResult = DirectoryRoot; + PrintDirectory(DirectoryRoot); } else if (PhonebookSyncState.InitialSyncComplete) @@ -1035,9 +1047,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco PrintDirectory(directoryResults); - DirectoryBrowseHistory.Add(directoryResults); - - OnDirectoryResultReturned(directoryResults); + CurrentDirectoryResult = directoryResults; } } @@ -1068,8 +1078,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// void OnDirectoryResultReturned(CodecDirectory result) { - CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); - // This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology var handler = DirectoryResultReturned; if (handler != null) @@ -1221,6 +1229,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// public void SearchDirectory(string searchString) { + DirectoryBrowseHistoryStack.Push(CurrentDirectoryResult); + SendText(string.Format("xCommand Phonebook Search SearchString: \"{0}\" PhonebookType: {1} ContactType: Contact Limit: {2}", searchString, PhonebookMode, PhonebookResultsLimit)); } @@ -1230,6 +1240,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// public void GetDirectoryFolderContents(string folderId) { + DirectoryBrowseHistoryStack.Push(CurrentDirectoryResult); + SendText(string.Format("xCommand Phonebook Search FolderId: {0} PhonebookType: {1} ContactType: Any Limit: {2}", folderId, PhonebookMode, PhonebookResultsLimit)); } @@ -1239,24 +1251,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// public void GetDirectoryParentFolderContents() { - var currentDirectory = new CodecDirectory(); - - if (DirectoryBrowseHistory.Count > 0) + if (DirectoryBrowseHistoryStack.Count == 0) { - var lastItemIndex = DirectoryBrowseHistory.Count - 1; - var parentDirectoryContents = DirectoryBrowseHistory[lastItemIndex]; - - DirectoryBrowseHistory.Remove(DirectoryBrowseHistory[lastItemIndex]); - - currentDirectory = parentDirectoryContents; - - } - else - { - currentDirectory = DirectoryRoot; + return; } - OnDirectoryResultReturned(currentDirectory); + CurrentDirectoryResult = DirectoryBrowseHistoryStack.Pop(); } /// @@ -1264,9 +1264,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// public void SetCurrentDirectoryToRoot() { - DirectoryBrowseHistory.Clear(); + DirectoryBrowseHistoryStack.Clear(); - OnDirectoryResultReturned(DirectoryRoot); + CurrentDirectoryResult = DirectoryRoot; } /// From e7cfe1143db2092af3c213b7442ae2ac8f9d7941 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 25 Aug 2021 16:24:18 -0600 Subject: [PATCH 18/19] fix(essentials): updates MockVc to instantiate the OsdSource and add its tie line --- .../VideoCodec/MockVC/MockVC.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs index 5d701f7b..e8988ad2 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs @@ -78,6 +78,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec SetupCameras(); + CreateOsdSource(); + SetIsReady(); } @@ -117,6 +119,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } bool _StandbyIsOn; + /// + /// Creates the fake OSD source, and connects it's AudioVideo output to the CodecOsdIn input + /// to enable routing + /// + void CreateOsdSource() + { + OsdSource = new DummyRoutingInputsDevice(Key + "[osd]"); + DeviceManager.AddDevice(OsdSource); + var tl = new TieLine(OsdSource.AudioVideoOutputPort, CodecOsdIn); + TieLineCollection.Default.Add(tl); + } /// /// Dials, yo! From acd2be3679a5a1df6bd2dc4719a148cd3766fe0b Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 25 Aug 2021 17:23:24 -0600 Subject: [PATCH 19/19] feat(essentials): Updates to get scenarios to activate/deactivate --- .../Room/Combining/EssentialsRoomCombiner.cs | 16 +++++++++++++++- .../Room/Combining/IEssentialsRoomCombiner.cs | 5 +++++ .../Room/Combining/RoomCombinationScenario.cs | 10 ++++++++-- packages.config | 2 +- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs index d9886e70..820d363f 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/EssentialsRoomCombiner.cs @@ -171,8 +171,22 @@ namespace PepperDash.Essentials.Core { if (value != _currentScenario) { + // Deactivate the old scenario first + if (_currentScenario != null) + { + _currentScenario.Deactivate(); + } + _currentScenario = value; - Debug.Console(1, this, "Current Scenario: {0}", _currentScenario.Name); + + // Activate the new scenario + if (_currentScenario != null) + { + _currentScenario.Activate(); + + Debug.Console(1, this, "Current Scenario: {0}", _currentScenario.Name); + } + var handler = RoomCombinationScenarioChanged; if (handler != null) { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/IEssentialsRoomCombiner.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/IEssentialsRoomCombiner.cs index c0c8101b..e6bdd983 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/IEssentialsRoomCombiner.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/IEssentialsRoomCombiner.cs @@ -78,6 +78,11 @@ namespace PepperDash.Essentials.Core /// void Activate(); + /// + /// Deactivates this room combination scenario + /// + void Deactivate(); + /// /// The state of the partitions that would activate this scenario /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/RoomCombinationScenario.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/RoomCombinationScenario.cs index a5534edc..460241a0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/RoomCombinationScenario.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Combining/RoomCombinationScenario.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Text; using Crestron.SimplSharp; +using PepperDash.Core; + using Newtonsoft.Json; namespace PepperDash.Essentials.Core @@ -27,9 +29,9 @@ namespace PepperDash.Essentials.Core public BoolFeedback IsActiveFeedback { get; private set; } - List activationActions; + private List activationActions; - List deactivationActions; + private List deactivationActions; public RoomCombinationScenario(RoomCombinationScenarioConfig config) { @@ -52,6 +54,8 @@ namespace PepperDash.Essentials.Core public void Activate() { + Debug.Console(1, "Activating Scenario: '{0}' with {1} action(s) defined", Name, activationActions.Count); + if (activationActions != null) { foreach (var action in activationActions) @@ -66,6 +70,8 @@ namespace PepperDash.Essentials.Core public void Deactivate() { + Debug.Console(1, "Deactivating Scenario: '{0}' with {1} action(s) defined", Name, deactivationActions.Count); + if (deactivationActions != null) { foreach (var action in deactivationActions) diff --git a/packages.config b/packages.config index 3494f2eb..06d30eaa 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + \ No newline at end of file