Updates from bench testing RoomOnToDefaultSourceWhenOccupied. Now tested and working using config file values.

This commit is contained in:
Neil Dorin
2018-08-28 17:03:07 -06:00
parent bd31d76e8b
commit 7ba2429cbf
5 changed files with 415 additions and 296 deletions

View File

@@ -43,19 +43,21 @@ namespace PepperDash.Essentials.Room.Behaviours
public RoomOnToDefaultSourceWhenOccupied(string key, RoomOnToDefaultSourceWhenOccupiedConfig config) public RoomOnToDefaultSourceWhenOccupied(string key, RoomOnToDefaultSourceWhenOccupiedConfig config)
: base(key) : base(key)
{ {
CrestronConsole.AddNewConsoleCommand((o) => FeatureEventGroup.ClearAllEvents(), "ClearAllEvents", "Clears all scheduled events for this group", ConsoleAccessLevelEnum.AccessAdministrator);
Config = config; Config = config;
FeatureEventGroup = new ScheduledEventGroup(this.Key); FeatureEventGroup = new ScheduledEventGroup(this.Key);
FeatureEventGroup.RetrieveAllEvents(); FeatureEventGroup.RetrieveAllEvents();
// Add to the global class for tracking
//Global.Scheduler.AddEventGroup(FeatureEventGroup);
AddPostActivationAction(() => AddPostActivationAction(() =>
{ {
if (Room.RoomOccupancy != null) // Subscribe to room event to know when RoomOccupancy is set and ready to be subscribed to
Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += new EventHandler<FeedbackEventArgs>(RoomIsOccupiedFeedback_OutputChange); if (Room != null)
Room.RoomOccupancyIsSet += new EventHandler<EventArgs>(RoomOccupancyIsSet);
else else
Debug.Console(1, this, "Room has no RoomOccupancy object set"); Debug.Console(1, this, "Room has no RoomOccupancy object set");
@@ -74,11 +76,6 @@ namespace PepperDash.Essentials.Room.Behaviours
if (Room != null) if (Room != null)
{ {
// Creates the event group and adds it to the Global Scheduler list
//Global.Scheduler.AddEventGroup(FeatureEventGroup);
try try
{ {
FeatureEnabledTime = DateTime.Parse(Config.OccupancyStartTime); FeatureEnabledTime = DateTime.Parse(Config.OccupancyStartTime);
@@ -127,6 +124,21 @@ namespace PepperDash.Essentials.Room.Behaviours
return base.CustomActivate(); return base.CustomActivate();
} }
/// <summary>
/// Subscribe to feedback from RoomIsOccupiedFeedback on Room
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void RoomOccupancyIsSet(object sender, EventArgs e)
{
if (Room.RoomOccupancy != null)
{
Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange;
Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += new EventHandler<FeedbackEventArgs>(RoomIsOccupiedFeedback_OutputChange);
Debug.Console(1, this, "Subscribed to RoomOccupancy status from: '{0}'", Room.Key);
}
}
void FeatureEventGroup_UserGroupCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type) void FeatureEventGroup_UserGroupCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type)
{ {
if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration) if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration)
@@ -136,13 +148,13 @@ namespace PepperDash.Essentials.Room.Behaviours
if (Config.EnableRoomOnWhenOccupied) if (Config.EnableRoomOnWhenOccupied)
FeatureEnabled = true; FeatureEnabled = true;
Debug.Console(1, this, "*****Feature Enabled.*****"); Debug.Console(1, this, "*****Feature Enabled by event.*****");
} }
else if (SchEvent.Name == FeatureDisableEventName) else if (SchEvent.Name == FeatureDisableEventName)
{ {
FeatureEnabled = false; FeatureEnabled = false;
Debug.Console(1, this, "*****Feature Disabled.*****"); Debug.Console(1, this, "*****Feature Disabled by event.*****");
} }
} }
} }
@@ -159,7 +171,11 @@ namespace PepperDash.Essentials.Room.Behaviours
{ {
if (DateTime.Now.CompareTo(FeatureEnabledTime) > 0 && FeatureDisabledTime.CompareTo(DateTime.Now) >= 0) if (DateTime.Now.CompareTo(FeatureEnabledTime) > 0 && FeatureDisabledTime.CompareTo(DateTime.Now) >= 0)
{ {
enabled = true; if (SchedulerUtilities.CheckIfDayOfWeekMatchesRecurrenceDays(DateTime.Now, FeatureEnableEvent.Recurrence.RecurrenceDays))
{
Debug.Console(1, this, "*****Feature Enabled by startup check.*****");
enabled = true;
}
} }
} }
return enabled; return enabled;
@@ -172,6 +188,7 @@ namespace PepperDash.Essentials.Room.Behaviours
/// <param name="e"></param> /// <param name="e"></param>
void RoomIsOccupiedFeedback_OutputChange(object sender, FeedbackEventArgs e) void RoomIsOccupiedFeedback_OutputChange(object sender, FeedbackEventArgs e)
{ {
Debug.Console(1, this, "RoomIsOccupiedFeeback.OutputChange event fired. e.BoolValue: {0}", e.BoolValue);
if(e.BoolValue) if(e.BoolValue)
{ {
// Occupancy detected // Occupancy detected
@@ -179,8 +196,11 @@ namespace PepperDash.Essentials.Room.Behaviours
if (FeatureEnabled) if (FeatureEnabled)
{ {
// Check room power state first // Check room power state first
if(!Room.OnFeedback.BoolValue) if (!Room.OnFeedback.BoolValue)
Room.PowerOnToDefaultOrLastSource(); {
Debug.Console(1, this, "Powering Room on to default source");
Room.RunDefaultPresentRoute();
}
} }
} }
} }
@@ -206,17 +226,34 @@ namespace PepperDash.Essentials.Room.Behaviours
{ {
schEvent.Description = "Enables the RoomOnToDefaultSourceWhenOccupiedFeature"; schEvent.Description = "Enables the RoomOnToDefaultSourceWhenOccupiedFeature";
var eventRecurrennce = CalculateDaysOfWeekRecurrence();
var eventTime = new DateTime();
// Check to make sure the date for this event is in the future // Check to make sure the date for this event is in the future
if (DateTime.Now.CompareTo(FeatureEnabledTime) > 0) if (DateTime.Now.CompareTo(FeatureEnabledTime) > 0)
schEvent.DateAndTime.SetAbsoluteEventTime(FeatureEnabledTime.AddDays(1)); eventTime = FeatureEnabledTime.AddDays(1);
else else
schEvent.DateAndTime.SetAbsoluteEventTime(FeatureEnabledTime); eventTime = FeatureEnabledTime;
Debug.Console(1, this, "eventTime (before recurrence check): {0}", eventTime);
// Check day of week against recurrence days and move date ahead as necessary to avoid throwing an exception by trying to set the event
// start date on a day of the week that doesn't match teh recurrence values
while(!SchedulerUtilities.CheckIfDayOfWeekMatchesRecurrenceDays(eventTime, eventRecurrennce))
{
eventTime = eventTime.AddDays(1);
Debug.Console(1, this, "eventTime does not fall on a recurrence weekday. eventTime: {0}", eventTime);
}
schEvent.DateAndTime.SetAbsoluteEventTime(eventTime);
Debug.Console(1, this, "Event '{0}' Absolute time set to {1}", schEvent.Name, schEvent.DateAndTime.ToString()); Debug.Console(1, this, "Event '{0}' Absolute time set to {1}", schEvent.Name, schEvent.DateAndTime.ToString());
CalculateAndSetAcknowledgeExpirationTimeout(schEvent, FeatureEnabledTime, FeatureDisabledTime); CalculateAndSetAcknowledgeExpirationTimeout(schEvent, FeatureEnabledTime, FeatureDisabledTime);
schEvent.Recurrence.Weekly((ScheduledEventCommon.eWeekDays)CalculateDaysEnum()); schEvent.Recurrence.Weekly(eventRecurrennce);
} }
else if (schEvent.Name == FeatureDisableEventName) else if (schEvent.Name == FeatureDisableEventName)
{ {
@@ -236,6 +273,8 @@ namespace PepperDash.Essentials.Room.Behaviours
} }
} }
void CalculateAndSetAcknowledgeExpirationTimeout(ScheduledEvent schEvent, DateTime time1, DateTime time2) void CalculateAndSetAcknowledgeExpirationTimeout(ScheduledEvent schEvent, DateTime time1, DateTime time2)
{ {
Debug.Console(1, this, "time1.Hour = {0}", time1.Hour); Debug.Console(1, this, "time1.Hour = {0}", time1.Hour);
@@ -262,6 +301,40 @@ namespace PepperDash.Essentials.Room.Behaviours
schEvent.AcknowledgeExpirationTimeout.Minute = (ushort)(ackExpMinutes); schEvent.AcknowledgeExpirationTimeout.Minute = (ushort)(ackExpMinutes);
} }
/// <summary>
/// Checks existing event to see if it matches the execution time
/// </summary>
/// <param name="existingEvent"></param>
/// <returns></returns>
bool CheckExistingEventTimeForMatch(ScheduledEvent existingEvent, DateTime newTime)
{
bool isMatch = true;
// Check to see if hour and minute match
if (existingEvent.DateAndTime.Hour != newTime.Hour || existingEvent.DateAndTime.Minute != newTime.Minute)
return false;
return isMatch;
}
/// <summary>
/// Checks existing event to see if it matches the recurrence days
/// </summary>
/// <param name="existingEvent"></param>
/// <param name="eWeekdays"></param>
/// <returns></returns>
bool CheckExistingEventRecurrenceForMatch(ScheduledEvent existingEvent, ScheduledEventCommon.eWeekDays eWeekdays)
{
bool isMatch = true;
// Check to see if recurrence matches
if (eWeekdays != existingEvent.Recurrence.RecurrenceDays)
return false;
return isMatch;
}
/// <summary> /// <summary>
/// Adds the Enable event to the local event group and sets its properties based on config /// Adds the Enable event to the local event group and sets its properties based on config
/// </summary> /// </summary>
@@ -273,11 +346,21 @@ namespace PepperDash.Essentials.Room.Behaviours
} }
else else
{ {
// Check if existing event has same time and recurrence as config values
FeatureEnableEvent = FeatureEventGroup.ScheduledEvents[FeatureEnableEventName]; FeatureEnableEvent = FeatureEventGroup.ScheduledEvents[FeatureEnableEventName];
Debug.Console(1, this, "Enable event already found in group"); Debug.Console(1, this, "Enable event already found in group");
// TODO: Check config times and days against DateAndTime of existing event. If different, may need to remove event and recreate? // Check config times and days against DateAndTime of existing event. If different, delete existing event and create new event
if(!CheckExistingEventTimeForMatch(FeatureEnableEvent, FeatureEnabledTime) || !CheckExistingEventRecurrenceForMatch(FeatureEnableEvent, CalculateDaysOfWeekRecurrence()))
{
Debug.Console(1, this, "Existing event does not match new config properties. Deleting exisiting event: '{0}'", FeatureEnableEvent.Name);
FeatureEventGroup.DeleteEvent(FeatureEnableEvent);
FeatureEnableEvent = null;
CreateEvent(FeatureEnableEvent, FeatureEnableEventName);
}
} }
} }
@@ -296,34 +379,43 @@ namespace PepperDash.Essentials.Room.Behaviours
FeatureDisableEvent = FeatureEventGroup.ScheduledEvents[FeatureDisableEventName]; FeatureDisableEvent = FeatureEventGroup.ScheduledEvents[FeatureDisableEventName];
Debug.Console(1, this, "Disable event already found in group"); Debug.Console(1, this, "Disable event already found in group");
// TODO: Check config times and days against DateAndTime of existing event. If different, may need to remove event and recreate? // Check config times against DateAndTime of existing event. If different, delete existing event and create new event
} if(!CheckExistingEventTimeForMatch(FeatureDisableEvent, FeatureDisabledTime))
{
Debug.Console(1, this, "Existing event does not match new config properties. Deleting exisiting event: '{0}'", FeatureDisableEvent.Name);
FeatureEventGroup.DeleteEvent(FeatureDisableEvent);
FeatureDisableEvent = null;
CreateEvent(FeatureDisableEvent, FeatureDisableEventName);
}
}
} }
/// <summary> /// <summary>
/// Calculates the correct enum value for the event recurrence based on the config values /// Calculates the correct bitfield enum value for the event recurrence based on the config values
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
ScheduledEventCommon.eWeekDays CalculateDaysEnum() ScheduledEventCommon.eWeekDays CalculateDaysOfWeekRecurrence()
{ {
ScheduledEventCommon.eWeekDays value = new ScheduledEventCommon.eWeekDays(); ScheduledEventCommon.eWeekDays value = new ScheduledEventCommon.eWeekDays();
if (Config.EnableSunday) if (Config.EnableSunday)
value = value + (int)ScheduledEventCommon.eWeekDays.Sunday; value = value | ScheduledEventCommon.eWeekDays.Sunday;
if (Config.EnableMonday) if (Config.EnableMonday)
value = value + (int)ScheduledEventCommon.eWeekDays.Monday; value = value | ScheduledEventCommon.eWeekDays.Monday;
if (Config.EnableTuesday) if (Config.EnableTuesday)
value = value + (int)ScheduledEventCommon.eWeekDays.Tuesday; value = value | ScheduledEventCommon.eWeekDays.Tuesday;
if (Config.EnableWednesday) if (Config.EnableWednesday)
value = value + (int)ScheduledEventCommon.eWeekDays.Wednesday; value = value | ScheduledEventCommon.eWeekDays.Wednesday;
if (Config.EnableThursday) if (Config.EnableThursday)
value = value + (int)ScheduledEventCommon.eWeekDays.Thursday; value = value | ScheduledEventCommon.eWeekDays.Thursday;
if (Config.EnableFriday) if (Config.EnableFriday)
value = value + (int)ScheduledEventCommon.eWeekDays.Friday; value = value | ScheduledEventCommon.eWeekDays.Friday;
if (Config.EnableSaturday) if (Config.EnableSaturday)
value = value + (int)ScheduledEventCommon.eWeekDays.Saturday; value = value | ScheduledEventCommon.eWeekDays.Saturday;
return value; return value;
} }

View File

@@ -212,10 +212,13 @@ namespace PepperDash.Essentials
/// <summary> /// <summary>
/// Routes the default source item, if any /// Routes the default source item, if any
/// </summary> /// </summary>
public bool RunDefaultPresentRoute() public override bool RunDefaultPresentRoute()
{ {
if(DefaultSourceItem == null) if (DefaultSourceItem == null)
return false; {
Debug.Console(0, this, "Unable to run default present route, DefaultSourceItem is null.");
return false;
}
RunRouteAction(DefaultSourceItem); RunRouteAction(DefaultSourceItem);
return true; return true;

View File

@@ -283,10 +283,11 @@ namespace PepperDash.Essentials
/// <summary> /// <summary>
/// Routes the default source item, if any. Returns true when default route exists /// Routes the default source item, if any. Returns true when default route exists
/// </summary> /// </summary>
public bool RunDefaultPresentRoute() public override bool RunDefaultPresentRoute()
{ {
//if (DefaultSourceItem != null) if (DefaultSourceItem != null)
RunRouteAction(DefaultSourceItem); RunRouteAction(DefaultSourceItem);
return DefaultSourceItem != null; return DefaultSourceItem != null;
} }

View File

@@ -1,273 +1,294 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.Scheduler; using Crestron.SimplSharp.Scheduler;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Occupancy; using PepperDash.Essentials.Devices.Common.Occupancy;
namespace PepperDash.Essentials namespace PepperDash.Essentials
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public abstract class EssentialsRoomBase : Device public abstract class EssentialsRoomBase : Device
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public BoolFeedback OnFeedback { get; private set; } public BoolFeedback OnFeedback { get; private set; }
public BoolFeedback IsWarmingUpFeedback { get; private set; } /// <summary>
public BoolFeedback IsCoolingDownFeedback { get; private set; } /// Fires when the RoomOccupancy object is set
/// </summary>
public IOccupancyStatusProvider RoomOccupancy { get; private set; } public event EventHandler<EventArgs> RoomOccupancyIsSet;
public bool OccupancyStatusProviderIsRemote { get; private set; } public BoolFeedback IsWarmingUpFeedback { get; private set; }
public BoolFeedback IsCoolingDownFeedback { get; private set; }
protected abstract Func<bool> IsWarmingFeedbackFunc { get; }
protected abstract Func<bool> IsCoolingFeedbackFunc { get; } public IOccupancyStatusProvider RoomOccupancy { get; private set; }
/// <summary> public bool OccupancyStatusProviderIsRemote { get; private set; }
/// Timer used for informing the UIs of a shutdown
/// </summary> protected abstract Func<bool> IsWarmingFeedbackFunc { get; }
public SecondsCountdownTimer ShutdownPromptTimer { get; private set; } protected abstract Func<bool> IsCoolingFeedbackFunc { get; }
/// <summary> /// <summary>
/// /// Timer used for informing the UIs of a shutdown
/// </summary> /// </summary>
public int ShutdownPromptSeconds { get; set; } public SecondsCountdownTimer ShutdownPromptTimer { get; private set; }
public int ShutdownVacancySeconds { get; set; }
public eShutdownType ShutdownType { get; private set; } /// <summary>
///
public PepperDash.Essentials.Room.EssentialsRoomEmergencyBase Emergency { get; set; } /// </summary>
public int ShutdownPromptSeconds { get; set; }
public PepperDash.Essentials.Devices.Common.Microphones.MicrophonePrivacyController MicrophonePrivacy { get; set; } public int ShutdownVacancySeconds { get; set; }
public eShutdownType ShutdownType { get; private set; }
public string LogoUrl { get; set; }
public PepperDash.Essentials.Room.EssentialsRoomEmergencyBase Emergency { get; set; }
protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; }
public PepperDash.Essentials.Devices.Common.Microphones.MicrophonePrivacyController MicrophonePrivacy { get; set; }
public eVacancyMode VacancyMode { get; private set; }
public string LogoUrl { get; set; }
/// <summary>
/// Seconds after vacancy prompt is displayed until shutdown protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; }
/// </summary>
protected int RoomVacancyShutdownSeconds; public eVacancyMode VacancyMode { get; private set; }
/// <summary> /// <summary>
/// Seconds after vacancy detected until prompt is displayed /// Seconds after vacancy prompt is displayed until shutdown
/// </summary> /// </summary>
protected int RoomVacancyShutdownSeconds;
/// <summary>
/// Seconds after vacancy detected until prompt is displayed
/// </summary>
protected int RoomVacancyShutdownPromptSeconds; protected int RoomVacancyShutdownPromptSeconds;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
protected abstract Func<bool> OnFeedbackFunc { get; } protected abstract Func<bool> OnFeedbackFunc { get; }
protected Dictionary<IBasicVolumeWithFeedback, uint> SavedVolumeLevels = new Dictionary<IBasicVolumeWithFeedback, uint>(); protected Dictionary<IBasicVolumeWithFeedback, uint> SavedVolumeLevels = new Dictionary<IBasicVolumeWithFeedback, uint>();
/// <summary> /// <summary>
/// When volume control devices change, should we zero the one that we are leaving? /// When volume control devices change, should we zero the one that we are leaving?
/// </summary> /// </summary>
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; } public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="name"></param> /// <param name="name"></param>
public EssentialsRoomBase(string key, string name) : base(key, name) public EssentialsRoomBase(string key, string name) : base(key, name)
{ {
// Setup the ShutdownPromptTimer // Setup the ShutdownPromptTimer
ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer"); ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer");
ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) => ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) =>
{ {
if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue) if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue)
ShutdownType = eShutdownType.None; ShutdownType = eShutdownType.None;
}; };
ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered
ShutdownPromptSeconds = 60; ShutdownPromptSeconds = 60;
ShutdownVacancySeconds = 120; ShutdownVacancySeconds = 120;
ShutdownType = eShutdownType.None; ShutdownType = eShutdownType.None;
RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer"); RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer");
//RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) => //RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) =>
//{ //{
// if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue) // if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue)
// ShutdownType = ShutdownType.Vacancy; // ShutdownType = ShutdownType.Vacancy;
//}; //};
RoomVacancyShutdownTimer.HasFinished += new EventHandler<EventArgs>(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered RoomVacancyShutdownTimer.HasFinished += new EventHandler<EventArgs>(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered
RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning
RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt
VacancyMode = eVacancyMode.None; VacancyMode = eVacancyMode.None;
OnFeedback = new BoolFeedback(OnFeedbackFunc); OnFeedback = new BoolFeedback(OnFeedbackFunc);
IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc); IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc);
IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc); IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc);
}
AddPostActivationAction(() =>
void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e) {
{ if (RoomOccupancy != null)
switch (VacancyMode) OnRoomOccupancyIsSet();
{ });
case eVacancyMode.None:
StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
break;
case eVacancyMode.InInitialVacancy:
StartRoomVacancyTimer(eVacancyMode.InShutdownWarning);
break;
case eVacancyMode.InShutdownWarning:
{
StartShutdown(eShutdownType.Vacancy);
Debug.Console(0, this, "Shutting Down due to vacancy.");
break;
}
default:
break;
}
}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
public void StartShutdown(eShutdownType type)
{
// Check for shutdowns running. Manual should override other shutdowns
if (type == eShutdownType.Manual)
ShutdownPromptTimer.SecondsToCount = ShutdownPromptSeconds;
else if (type == eShutdownType.Vacancy)
ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds;
ShutdownType = type;
ShutdownPromptTimer.Start();
}
public void StartRoomVacancyTimer(eVacancyMode mode)
{
if (mode == eVacancyMode.None)
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds;
else if (mode == eVacancyMode.InInitialVacancy)
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds;
VacancyMode = mode;
RoomVacancyShutdownTimer.Start();
Debug.Console(0, this, "Vacancy Timer Started.");
}
/// <summary>
/// Resets the vacancy mode and shutsdwon the room
/// </summary>
public void Shutdown()
{
VacancyMode = eVacancyMode.None;
EndShutdown();
}
/// <summary>
/// This method is for the derived class to define it's specific shutdown
/// requirements but should not be called directly. It is called by Shutdown()
/// </summary>
protected abstract void EndShutdown();
/// <summary>
/// Override this to implement a default volume level(s) method
/// </summary>
public abstract void SetDefaultLevels();
/// <summary>
/// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device
/// </summary>
/// <param name="statusProvider"></param>
public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes)
{
if (statusProvider == null)
{
Debug.Console(0, this, "ERROR: Occupancy sensor device is null");
return;
}
// If status provider is fusion, set flag to remote
if (statusProvider is PepperDash.Essentials.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase)
OccupancyStatusProviderIsRemote = true;
if(timeoutMinutes > 0)
RoomVacancyShutdownSeconds = timeoutMinutes * 60;
RoomOccupancy = statusProvider;
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
} }
void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e)
{
switch (VacancyMode)
{
case eVacancyMode.None:
StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
break;
case eVacancyMode.InInitialVacancy:
StartRoomVacancyTimer(eVacancyMode.InShutdownWarning);
break;
case eVacancyMode.InShutdownWarning:
{
StartShutdown(eShutdownType.Vacancy);
Debug.Console(0, this, "Shutting Down due to vacancy.");
break;
}
default:
break;
}
}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
public void StartShutdown(eShutdownType type)
{
// Check for shutdowns running. Manual should override other shutdowns
if (type == eShutdownType.Manual)
ShutdownPromptTimer.SecondsToCount = ShutdownPromptSeconds;
else if (type == eShutdownType.Vacancy)
ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds;
ShutdownType = type;
ShutdownPromptTimer.Start();
}
public void StartRoomVacancyTimer(eVacancyMode mode)
{
if (mode == eVacancyMode.None)
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds;
else if (mode == eVacancyMode.InInitialVacancy)
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds;
VacancyMode = mode;
RoomVacancyShutdownTimer.Start();
Debug.Console(0, this, "Vacancy Timer Started.");
}
/// <summary>
/// Resets the vacancy mode and shutsdwon the room
/// </summary>
public void Shutdown()
{
VacancyMode = eVacancyMode.None;
EndShutdown();
}
/// <summary>
/// This method is for the derived class to define it's specific shutdown
/// requirements but should not be called directly. It is called by Shutdown()
/// </summary>
protected abstract void EndShutdown();
/// <summary>
/// Override this to implement a default volume level(s) method
/// </summary>
public abstract void SetDefaultLevels();
/// <summary>
/// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device
/// </summary>
/// <param name="statusProvider"></param>
public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes)
{
if (statusProvider == null)
{
Debug.Console(0, this, "ERROR: Occupancy sensor device is null");
return;
}
// If status provider is fusion, set flag to remote
if (statusProvider is PepperDash.Essentials.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase)
OccupancyStatusProviderIsRemote = true;
if(timeoutMinutes > 0)
RoomVacancyShutdownSeconds = timeoutMinutes * 60;
RoomOccupancy = statusProvider;
OnRoomOccupancyIsSet();
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange;
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
Debug.Console(0, this, "Room Occupancy set to device: '{0}'", (statusProvider as Device).Key);
}
void OnRoomOccupancyIsSet()
{
var handler = RoomOccupancyIsSet;
if (handler != null)
handler(this, new EventArgs());
}
/// <summary>
/// To allow base class to power room on to last source
/// </summary>
public abstract void PowerOnToDefaultOrLastSource();
/// <summary> /// <summary>
/// To allow base class to power room on to default source /// To allow base class to power room on to default source
/// </summary> /// </summary>
public abstract void PowerOnToDefaultOrLastSource(); /// <returns></returns>
public abstract bool RunDefaultPresentRoute();
void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
{ void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false) {
{ if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false)
Debug.Console(1, this, "Notice: Vacancy Detected"); {
// Trigger the timer when the room is vacant Debug.Console(1, this, "Notice: Vacancy Detected");
StartRoomVacancyTimer(eVacancyMode.InInitialVacancy); // Trigger the timer when the room is vacant
} StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
else }
{ else
Debug.Console(1, this, "Notice: Occupancy Detected"); {
// Reset the timer when the room is occupied Debug.Console(1, this, "Notice: Occupancy Detected");
RoomVacancyShutdownTimer.Cancel(); // Reset the timer when the room is occupied
} RoomVacancyShutdownTimer.Cancel();
}
} }
/// <summary> /// <summary>
/// Sets up events in the scheduler for the start and end times of the appropriate days to enable and disable the RoomOccupancyPowerOnIsEnabled flag /// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed
/// </summary> /// </summary>
void SetUpOccupancyRoomOnEventsInScheduler() /// <param name="o"></param>
{ public abstract void RoomVacatedForTimeoutPeriod(object o);
}
}
/// <summary>
/// <summary> /// To describe the various ways a room may be shutting down
/// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed /// </summary>
/// </summary> public enum eShutdownType
/// <param name="o"></param> {
public abstract void RoomVacatedForTimeoutPeriod(object o); None = 0,
} External,
Manual,
/// <summary> Vacancy
/// To describe the various ways a room may be shutting down }
/// </summary>
public enum eShutdownType public enum eVacancyMode
{ {
None = 0, None = 0,
External, InInitialVacancy,
Manual, InShutdownWarning
Vacancy }
}
/// <summary>
public enum eVacancyMode ///
{ /// </summary>
None = 0, public enum eWarmingCoolingMode
InInitialVacancy, {
InShutdownWarning None,
} Warming,
Cooling
/// <summary> }
///
/// </summary>
public enum eWarmingCoolingMode
{
None,
Warming,
Cooling
}
} }

View File

@@ -29,3 +29,5 @@ devjson:1 {"deviceKey":"microphonePrivacyController-1", "methodName":"TogglePriv
devjson:1 {"deviceKey":"room1.InCallFeedback","methodName":"SetTestValue", "params": [ true ]} devjson:1 {"deviceKey":"room1.InCallFeedback","methodName":"SetTestValue", "params": [ true ]}
devjson:1 {"deviceKey":"room1.InCallFeedback","methodName":"ClearTestValue", "params": []} devjson:1 {"deviceKey":"room1.InCallFeedback","methodName":"ClearTestValue", "params": []}
devjson:3 {"deviceKey":"room1.RoomOccupancy.RoomIsOccupiedFeedback","methodName":"SetTestValue", "params": [ true ]}