diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs
index 29f24748..576e3cca 100644
--- a/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs
+++ b/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs
@@ -1,9 +1,7 @@
using System;
-using System.Linq;
+using System.Collections.Generic;
using Crestron.SimplSharp;
-
using Newtonsoft.Json;
-
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
@@ -11,59 +9,15 @@ using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
- public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasCurrentVolumeControls, IHasDefaultDisplay
- {
- //
- public event SourceInfoChangeHandler CurrentSourceChange;
+ public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IRunRouteAction,
+ IRunDefaultPresentRoute, IHasCurrentVolumeControls, IHasDefaultDisplay
+ {
+ public EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; private set; }
- public EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; private set; }
-
- public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
- public IRoutingSink DefaultAudioDevice { get; private set; }
- public IBasicVolumeControls DefaultVolumeControls { get; private set; }
-
- public bool ExcludeFromGlobalFunctions { get; set; }
-
- public string DefaultSourceItem { get; set; }
-
- public ushort DefaultVolume { get; set; }
-
- ///
- /// If room is off, enables power on to last source. Default true
- ///
- public bool EnablePowerOnToLastSource { get; set; }
- string _lastSourceKey;
-
- ///
- /// 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);
- }
- }
- SourceListItem _currentSourceInfo;
-
- public string CurrentSourceInfoKey { get; set; }
+ ///
+ /// If room is off, enables power on to last source. Default true
+ ///
+ public bool EnablePowerOnToLastSource { get; set; }
public EssentialsHuddleSpaceRoom(DeviceConfig config)
: base(config)
@@ -72,10 +26,12 @@ namespace PepperDash.Essentials
{
PropertiesConfig = JsonConvert.DeserializeObject
(config.Properties.ToString());
- DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching;
+ DefaultDisplay =
+ DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching;
- DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IRoutingSinkWithSwitching;
+ DefaultAudioDevice =
+ DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IRoutingSinkWithSwitching;
Initialize();
}
@@ -85,30 +41,36 @@ namespace PepperDash.Essentials
}
}
- private void Initialize()
- {
+ private void Initialize()
+ {
if (DefaultAudioDevice is IBasicVolumeControls)
+ {
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;
+ }
else if (DefaultAudioDevice is IHasVolumeDevice)
+ {
DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice;
+ }
CurrentVolumeControls = DefaultVolumeControls;
SourceListKey = "default";
EnablePowerOnToLastSource = true;
var disp = DefaultDisplay as DisplayBase;
- if (disp == null) return;
+ if (disp == null)
+ {
+ return;
+ }
IsWarmingFeedbackFunc = () => disp.IsWarmingUpFeedback.BoolValue;
IsCoolingFeedbackFunc = () => disp.IsCoolingDownFeedback.BoolValue;
OnFeedbackFunc = () => CurrentSourceInfo != null
- && CurrentSourceInfo.Type == eSourceListItemType.Route;
+ && CurrentSourceInfo.Type == eSourceListItemType.Route;
InitializeDisplay(disp);
- }
-
+ }
protected override void IsCoolingDownFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
{
@@ -119,7 +81,10 @@ namespace PepperDash.Essentials
{
var display = sender as DisplayBase;
- if (display == null) return;
+ if (display == null)
+ {
+ return;
+ }
if (display.PowerIsOnFeedback.BoolValue == OnFeedback.BoolValue)
{
@@ -156,10 +121,13 @@ namespace PepperDash.Essentials
protected override void CustomSetConfig(DeviceConfig config)
{
- var newPropertiesConfig = JsonConvert.DeserializeObject(config.Properties.ToString());
+ var newPropertiesConfig =
+ JsonConvert.DeserializeObject(config.Properties.ToString());
if (newPropertiesConfig != null)
+ {
PropertiesConfig = newPropertiesConfig;
+ }
ConfigWriter.UpdateRoomConfig(config);
}
@@ -173,7 +141,7 @@ namespace PepperDash.Essentials
RunDefaultPresentRoute();
- CrestronEnvironment.Sleep(1000);
+ //CrestronEnvironment.Sleep(1000); //why?
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room");
@@ -192,218 +160,38 @@ namespace PepperDash.Essentials
}
RunRouteAction(DefaultSourceItem);
- return true;
+ return true;
}
public override bool CustomActivate()
{
// Add Occupancy object from config
if (PropertiesConfig.Occupancy != null)
+ {
SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
+ }
LogoUrl = PropertiesConfig.Logo.GetUrl();
SourceListKey = PropertiesConfig.SourceListKey;
DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
- DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
+ DefaultVolume = (ushort) (PropertiesConfig.Volumes.Master.Level*65535/100);
return base.CustomActivate();
}
///
- ///
+ /// Will power the room on with the last-used source
///
- ///
- public void RunRouteAction(string routeKey)
- {
- RunRouteAction(routeKey, () => { });
- }
-
- ///
- ///
- ///
- ///
- ///
- public void RunRouteAction(string routeKey, string sourceListKey)
+ public override void PowerOnToDefaultOrLastSource()
{
- throw new NotImplementedException();
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- public void RunRouteAction(string routeKey, string sourceListKey, Action successCallback)
- {
- 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
- CrestronInvoke.BeginInvoke(o =>
+ if (!EnablePowerOnToLastSource || LastSourceKey == null)
{
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Run route action '{0}'", routeKey);
- var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
- if (dict == null)
- {
- Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
- return;
- }
-
- // Try to get the list item by it's string key
- if (!dict.ContainsKey(routeKey))
- {
- Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
- routeKey, SourceListKey);
- return;
- }
-
- var item = dict[routeKey];
- //Debug.Console(2, this, "Action {0} has {1} steps",
- // item.SourceKey, item.RouteList.Count);
-
- // End usage timer on last source
- if (!string.IsNullOrEmpty(_lastSourceKey))
- {
- var lastSource = dict[_lastSourceKey].SourceDevice;
-
- try
- {
- if (lastSource is IUsageTracking)
- (lastSource as IUsageTracking).UsageTracker.EndDeviceUsage();
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "*#* EXCEPTION in end usage tracking (257):\r{0}", e);
- }
- }
-
- // Let's run it
- if (routeKey.ToLower() != "roomoff")
- {
- _lastSourceKey = routeKey;
- }
- else
- {
- CurrentSourceInfoKey = null;
- }
-
- foreach (var route in item.RouteList)
- {
- // if there is a $defaultAll on route, run two separate
- if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
- {
- // Going to assume a single-path route for now
- var tempVideo = new SourceRouteListItem
- {
- DestinationKey = "$defaultDisplay",
- SourceKey = route.SourceKey,
- Type = eRoutingSignalType.Video
- };
- DoRoute(tempVideo);
-
- //var tempAudio = new SourceRouteListItem
- //{
- // DestinationKey = "$defaultAudio",
- // SourceKey = route.SourceKey,
- // Type = eRoutingSignalType.Audio
- //};
- //DoRoute(tempAudio);
- //continue; -- not sure why this was here
- }
- else
- DoRoute(route);
- }
-
- // Start usage timer on routed source
- if (item.SourceDevice is IUsageTracking)
- {
- (item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
- }
-
-
-
-
- // Set volume control, using default if non provided
- IBasicVolumeControls volDev = null;
- // Handle special cases for volume control
- if (string.IsNullOrEmpty(item.VolumeControlKey)
- || item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
- volDev = DefaultVolumeControls;
- else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
- volDev = DefaultDisplay as IBasicVolumeControls;
- // Or a specific device, probably rarely used.
- else
- {
- var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
- if (dev is IBasicVolumeControls)
- volDev = dev as IBasicVolumeControls;
- else if (dev is IHasVolumeDevice)
- volDev = (dev as IHasVolumeDevice).VolumeDevice;
- }
-
- if (volDev != CurrentVolumeControls)
- {
- // zero the volume on the device we are leaving.
- // Set the volume to default on device we are entering
- if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
- {
- var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
- SavedVolumeLevels[vd] = (uint) vd.VolumeLevelFeedback.IntValue;
- vd.SetVolume(0);
- }
- CurrentVolumeControls = volDev;
- if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
- {
- var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
- ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort) SavedVolumeLevels[vd] : DefaultVolume);
- vd.SetVolume(vol);
- }
- }
-
-
-
- // store the name and UI info for routes
- if (item.SourceKey == "$off")
- {
- CurrentSourceInfoKey = routeKey;
- CurrentSourceInfo = null;
- }
- else if (item.SourceKey != null)
- {
- CurrentSourceInfoKey = routeKey;
- CurrentSourceInfo = item;
- }
- // And finally, set the "control". This will trigger event
- //CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device;
-
- OnFeedback.FireUpdate();
-
- // report back when done
- if (successCallback != null)
- successCallback();
-
- }, 0); // end of CTimer
+ return;
+ }
+ RunRouteAction(LastSourceKey);
}
- ///
- /// Will power the room on with the last-used source
- ///
- public override void PowerOnToDefaultOrLastSource()
- {
- if (!EnablePowerOnToLastSource || _lastSourceKey == null)
- return;
- RunRouteAction(_lastSourceKey);
- }
-
///
/// Does what it says
///
@@ -412,64 +200,14 @@ namespace PepperDash.Essentials
Debug.Console(1, this, "Restoring default levels");
var vc = CurrentVolumeControls as IBasicVolumeWithFeedback;
if (vc != null)
+ {
vc.SetVolume(DefaultVolume);
+ }
}
- ///
- ///
- ///
- ///
- ///
- private bool DoRoute(SourceRouteListItem route)
- {
- IRoutingSink dest;
-
- if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
- dest = DefaultAudioDevice;
- else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
- dest = DefaultDisplay;
- else
- dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink;
-
- if (dest == null)
- {
- Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
- return false;
- }
-
- if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
- {
- dest.ReleaseRoute();
- if (dest is IPower)
- (dest as IPower).PowerOff();
- }
- else
- {
- var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
- if (source == null)
- {
- Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
- return false;
- }
- dest.ReleaseAndMakeRoute(source, route.Type);
- }
- return true;
- }
-
public override void RoomVacatedForTimeoutPeriod(object o)
{
- //Implement this
+ //TODO: Implement RoomVacatedForTimeoutPeriod
}
-
- ///
- /// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
- ///
- public static void AllRoomsOff()
- {
- var allRooms = DeviceManager.AllDevices.OfType().Where(d =>
- !d.ExcludeFromGlobalFunctions);
- foreach (var room in allRooms)
- room.RunRouteAction("roomOff");
- }
- }
+ }
}
\ No newline at end of file
diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs
index 94b9bfb0..6677351c 100644
--- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs
+++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs
@@ -331,7 +331,7 @@ namespace PepperDash.Essentials
///
///
///
- public void RunRouteAction(string routeKey)
+ public override void RunRouteAction(string routeKey)
{
RunRouteAction(routeKey, () => { });
}
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs
index df0aaa44..e9d844f0 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
+using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Devices;
@@ -9,9 +11,21 @@ namespace PepperDash.Essentials.Core
///
///
///
- public abstract class EssentialsRoomBase : ReconfigurableDevice
+ public abstract class EssentialsRoomBase : ReconfigurableDevice, IHasCurrentSourceInfoChange
{
public event EventHandler CurrentVolumeDeviceChange;
+ public event SourceInfoChangeHandler CurrentSourceChange;
+ public string CurrentSourceInfoKey { get; set; }
+
+ public IRoutingSinkWithSwitching DefaultDisplay { get; protected set; }
+ public IRoutingSink DefaultAudioDevice { get; protected set; }
+ public IBasicVolumeControls DefaultVolumeControls { get; protected set; }
+
+ protected CCriticalSection RoutingLock = new CCriticalSection();
+
+ public string DefaultSourceItem { get; set; }
+
+ public ushort DefaultVolume { get; set; }
///
/// Sets the volume control device, and attaches/removes InUseTrackers with "audio"
@@ -31,8 +45,10 @@ namespace PepperDash.Essentials.Core
if (handler != null)
{
- CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(CurrentAudioDevice, value, ChangeType.WillChange));
- CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(CurrentAudioDevice, value, ChangeType.DidChange));
+ CurrentVolumeDeviceChange(this,
+ new VolumeDeviceChangeEventArgs(CurrentAudioDevice, value, ChangeType.WillChange));
+ CurrentVolumeDeviceChange(this,
+ new VolumeDeviceChangeEventArgs(CurrentAudioDevice, value, ChangeType.DidChange));
}
var oldDevice = value as IInUseTracking;
@@ -43,6 +59,52 @@ namespace PepperDash.Essentials.Core
CurrentAudioDevice = value;
}
}
+
+ protected string LastSourceKey;
+
+ ///
+ /// 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);
+ }
+ }
+ }
+
+ private SourceListItem _currentSourceInfo;
+
+ public bool ExcludeFromGlobalFunctions { get; set; }
+
protected IBasicVolumeControls CurrentAudioDevice;
public BoolFeedback OnFeedback { get; private set; }
@@ -61,6 +123,7 @@ namespace PepperDash.Essentials.Core
protected Func IsWarmingFeedbackFunc;
protected Func IsCoolingFeedbackFunc;
+
///
/// The config name of the source list
///
@@ -100,42 +163,21 @@ namespace PepperDash.Essentials.Core
///
protected Func OnFeedbackFunc;
- protected Dictionary SavedVolumeLevels = new Dictionary();
+ protected Dictionary SavedVolumeLevels =
+ new Dictionary();
- ///
- /// When volume control devices change, should we zero the one that we are leaving?
- ///
- public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; }
+ ///
+ /// When volume control devices change, should we zero the one that we are leaving?
+ ///
+ public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; }
protected EssentialsRoomBase(DeviceConfig config)
: base(config)
{
- // Setup the ShutdownPromptTimer
- ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer");
- ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) =>
- {
- if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue)
- ShutdownType = eShutdownType.None;
- };
- ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered
+ SetupShutdownPrompt();
- ShutdownPromptSeconds = 60;
- ShutdownVacancySeconds = 120;
-
- ShutdownType = eShutdownType.None;
-
- RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer");
- //RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) =>
- //{
- // if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue)
- // ShutdownType = ShutdownType.Vacancy;
- //};
- RoomVacancyShutdownTimer.HasFinished += RoomVacancyShutdownPromptTimer_HasFinished; // Shutdown is triggered
-
- RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning
- RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt
- VacancyMode = eVacancyMode.None;
+ SetupRoomVacancyShutdown();
OnFeedback = new BoolFeedback(OnFeedbackFunc);
@@ -145,10 +187,42 @@ namespace PepperDash.Essentials.Core
AddPostActivationAction(() =>
{
if (RoomOccupancy != null)
+ {
OnRoomOccupancyIsSet();
+ }
});
}
+ private void SetupRoomVacancyShutdown()
+ {
+ RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer");
+
+ RoomVacancyShutdownTimer.HasFinished += RoomVacancyShutdownPromptTimer_HasFinished; // Shutdown is triggered
+
+ RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning
+ RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt
+ VacancyMode = eVacancyMode.None;
+ }
+
+ private void SetupShutdownPrompt()
+ {
+ // Setup the ShutdownPromptTimer
+ ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer");
+ ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) =>
+ {
+ if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue)
+ {
+ ShutdownType = eShutdownType.None;
+ }
+ };
+ ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered
+
+ ShutdownPromptSeconds = 60;
+ ShutdownVacancySeconds = 120;
+
+ ShutdownType = eShutdownType.None;
+ }
+
protected void InitializeDisplay(DisplayBase display)
{
// Link power, warming, cooling to display
@@ -188,11 +262,11 @@ namespace PepperDash.Essentials.Core
StartRoomVacancyTimer(eVacancyMode.InShutdownWarning);
break;
case eVacancyMode.InShutdownWarning:
- {
- StartShutdown(eShutdownType.Vacancy);
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting Down due to vacancy.");
- break;
- }
+ {
+ StartShutdown(eShutdownType.Vacancy);
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting Down due to vacancy.");
+ break;
+ }
}
}
@@ -216,7 +290,8 @@ namespace PepperDash.Essentials.Core
ShutdownType = type;
ShutdownPromptTimer.Start();
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "ShutdownPromptTimer Started. Type: {0}. Seconds: {1}", ShutdownType, ShutdownPromptTimer.SecondsToCount);
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "ShutdownPromptTimer Started. Type: {0}. Seconds: {1}",
+ ShutdownType, ShutdownPromptTimer.SecondsToCount);
}
public void StartRoomVacancyTimer(eVacancyMode mode)
@@ -236,7 +311,8 @@ namespace PepperDash.Essentials.Core
VacancyMode = mode;
RoomVacancyShutdownTimer.Start();
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Vacancy Timer Started. Mode: {0}. Seconds: {1}", VacancyMode, RoomVacancyShutdownTimer.SecondsToCount);
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Vacancy Timer Started. Mode: {0}. Seconds: {1}",
+ VacancyMode, RoomVacancyShutdownTimer.SecondsToCount);
}
///
@@ -269,23 +345,28 @@ namespace PepperDash.Essentials.Core
{
var provider = statusProvider as IKeyed;
- if (provider == null)
- {
- Debug.Console(0, this, "ERROR: Occupancy sensor device is null");
- return;
- }
+ if (provider == null)
+ {
+ Debug.Console(0, this, "ERROR: Occupancy sensor device is null");
+ return;
+ }
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Room Occupancy set to device: '{0}'", provider.Key);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Timeout Minutes from Config is: {0}", timeoutMinutes);
// If status provider is fusion, set flag to remote
if (statusProvider is Fusion.EssentialsHuddleSpaceFusionSystemControllerBase)
+ {
OccupancyStatusProviderIsRemote = true;
+ }
- if(timeoutMinutes > 0)
- RoomVacancyShutdownSeconds = timeoutMinutes * 60;
+ if (timeoutMinutes > 0)
+ {
+ RoomVacancyShutdownSeconds = timeoutMinutes*60;
+ }
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "RoomVacancyShutdownSeconds set to {0}", RoomVacancyShutdownSeconds);
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "RoomVacancyShutdownSeconds set to {0}",
+ RoomVacancyShutdownSeconds);
RoomOccupancy = statusProvider;
@@ -295,11 +376,13 @@ namespace PepperDash.Essentials.Core
OnRoomOccupancyIsSet();
}
- void OnRoomOccupancyIsSet()
+ private void OnRoomOccupancyIsSet()
{
var handler = RoomOccupancyIsSet;
if (handler != null)
+ {
handler(this, new EventArgs());
+ }
}
///
@@ -313,7 +396,7 @@ namespace PepperDash.Essentials.Core
///
public abstract bool RunDefaultPresentRoute();
- void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
+ private void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
{
if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false)
{
@@ -334,8 +417,303 @@ namespace PepperDash.Essentials.Core
///
///
public abstract void RoomVacatedForTimeoutPeriod(object o);
+
+ ///
+ ///
+ ///
+ ///
+ public virtual void RunRouteAction(string routeKey)
+ {
+ RunRouteAction(routeKey, String.Empty, () => { });
+ }
+
+ ///
+ /// Gets a source from config list SourceListKey and dynamically build and executes the
+ /// route or commands
+ ///
+ public virtual void RunRouteAction(string routeKey, Action successCallback)
+ {
+ RunRouteAction(routeKey, String.Empty, successCallback);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual void RunRouteAction(string routeKey, string sourceListKey)
+ {
+ RunRouteAction(routeKey, sourceListKey, () => { });
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual void RunRouteAction(string routeKey, string sourceListKey, Action successCallback)
+ {
+ var routeObject =
+ new {RouteKey = routeKey, SourceListKey = sourceListKey, SuccessCallback = successCallback};
+ CrestronInvoke.BeginInvoke(RunRouteAction, routeObject); // end of BeginInvoke
+ }
+
+ protected virtual void RunRouteAction(object routeObject)
+ {
+ try
+ {
+ RoutingLock.Enter();
+
+ var routeObj = new {RouteKey = "", SourceListKey = "", SuccessCallback = new Action(() => { })};
+
+ routeObj = Cast(routeObj, routeObject);
+
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Run route action '{0}'", routeObj.RouteKey);
+ var sourceList = GetSourceListForKey(routeObj.RouteKey, routeObj.SourceListKey);
+
+ if (sourceList == null)
+ {
+ Debug.Console(0, this, "No source list found for key {0}", routeObj.SourceListKey);
+ return;
+ }
+
+ var item = sourceList[routeObj.RouteKey];
+
+ // End usage timer on last source
+ StopUsageTrackingOnCurrentSource(sourceList);
+
+ // Let's run it
+ if (routeObj.RouteKey.ToLower() != "roomoff")
+ {
+ LastSourceKey = routeObj.RouteKey;
+ }
+ else
+ {
+ CurrentSourceInfoKey = null;
+ }
+
+ foreach (var route in item.RouteList)
+ {
+ var tempVideo = new SourceRouteListItem
+ {
+ DestinationKey = "$defaultDisplay",
+ SourceKey = route.SourceKey,
+ Type = eRoutingSignalType.Video
+ };
+
+ var routeItem = route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase)
+ ? tempVideo
+ : route;
+
+ DoRoute(routeItem);
+ }
+
+ // Start usage timer on routed source
+ if (item.SourceDevice is IUsageTracking)
+ {
+ (item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
+ }
+
+ // Set volume control, using default if non provided
+ SetVolumeControl(item);
+
+ // store the name and UI info for routes
+ if (item.SourceKey == "$off")
+ {
+ CurrentSourceInfoKey = routeObj.RouteKey;
+ CurrentSourceInfo = null;
+ }
+ else if (item.SourceKey != null)
+ {
+ CurrentSourceInfoKey = routeObj.RouteKey;
+ CurrentSourceInfo = item;
+ }
+
+ OnFeedback.FireUpdate();
+
+ // report back when done
+ if (routeObj.SuccessCallback != null)
+ {
+ routeObj.SuccessCallback();
+ }
+ }
+ finally
+ {
+ RoutingLock.Leave();
+ }
+ }
+
+ private static T Cast(T typeHolder, object m)
+ {
+ return (T) m;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected void DoRoute(SourceRouteListItem route)
+ {
+ var dest = GetDestination(route);
+
+ if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
+ {
+ dest.ReleaseRoute();
+ if (dest is IPower)
+ {
+ (dest as IPower).PowerOff();
+ }
+ }
+ else
+ {
+ var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
+ if (source == null)
+ {
+ Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey,
+ route.DestinationKey);
+ return;
+ }
+ dest.ReleaseAndMakeRoute(source, route.Type);
+ }
+ }
+
+ private IRoutingSink GetDestination(SourceRouteListItem route)
+ {
+ IRoutingSink dest;
+ if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
+ {
+ dest = DefaultAudioDevice;
+ }
+ else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
+ {
+ dest = DefaultDisplay;
+ }
+ else
+ {
+ dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink;
+ }
+
+ if (dest != null)
+ {
+ return dest;
+ }
+
+ Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
+ return dest;
+ }
+
+ private void SetVolumeControl(SourceListItem item)
+ {
+ 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;
+ }
+ 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)
+ {
+ return;
+ }
+
+ IBasicVolumeWithFeedback vd;
+ // zero the volume on the device we are leaving.
+ // Set the volume to default on device we are entering
+ if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
+ {
+ vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
+ SavedVolumeLevels[vd] = (uint) vd.VolumeLevelFeedback.IntValue;
+ vd.SetVolume(0);
+ }
+ CurrentVolumeControls = volDev;
+ if (!ZeroVolumeWhenSwtichingVolumeDevices || !(CurrentVolumeControls is IBasicVolumeWithFeedback))
+ {
+ return;
+ }
+
+ vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
+ var vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort) SavedVolumeLevels[vd] : DefaultVolume);
+ vd.SetVolume(vol);
+ }
+
+ private void StopUsageTrackingOnCurrentSource(Dictionary sourceList)
+ {
+ if (string.IsNullOrEmpty(LastSourceKey))
+ {
+ return;
+ }
+
+ var lastSource = sourceList[LastSourceKey].SourceDevice;
+
+ try
+ {
+ if (lastSource is IUsageTracking)
+ {
+ (lastSource as IUsageTracking).UsageTracker.EndDeviceUsage();
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "*#* EXCEPTION in end usage tracking (257):\r{0}", e);
+ }
+ }
+
+ private Dictionary GetSourceListForKey(string routeKey, string sourceListKey)
+ {
+ var slKey = String.IsNullOrEmpty(sourceListKey) ? SourceListKey : sourceListKey;
+
+ var sourceList = ConfigReader.ConfigObject.GetSourceListForKey(slKey);
+
+ if (sourceList == null)
+ {
+ Debug.Console(1, this, "WARNING: Config source list '{0}' not found", slKey);
+ return null;
+ }
+
+ // Try to get the list item by it's string key
+ if (sourceList.ContainsKey(routeKey))
+ {
+ return sourceList;
+ }
+
+ Debug.Console(1, this, "WARNING: No source list '{0}' found in config source lists '{1}'",
+ routeKey, SourceListKey);
+ return null;
+ }
+
+ ///
+ /// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
+ ///
+ public static void AllRoomsOff()
+ {
+ var allRooms = DeviceManager.AllDevices.OfType().Where(d =>
+ !d.ExcludeFromGlobalFunctions);
+ foreach (var room in allRooms)
+ {
+ room.RunRouteAction("roomOff");
+ }
+ }
}
-
+
///
/// To describe the various ways a room may be shutting down
///
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs
index cfd6f09e..35b431d9 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs
@@ -139,7 +139,7 @@ namespace PepperDash.Essentials.Core
}
}
- public class RoutingOutputPort : RoutingPort
+ public class RoutingOutputPort : RoutingPort, IInUseTracking
{
///
/// The IRoutingOutputs object this port lives on