Mega refactor in progress

This commit is contained in:
Neil Dorin
2019-10-23 22:29:04 -06:00
parent 407a354cfe
commit 13132c29fc
38 changed files with 1068 additions and 1369 deletions

View File

@@ -0,0 +1,525 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.Scheduler;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Devices;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// A device that when linked to a room can power the room on when enabled during scheduled hours.
/// </summary>
public class RoomOnToDefaultSourceWhenOccupied : ReconfigurableDevice
{
RoomOnToDefaultSourceWhenOccupiedConfig PropertiesConfig;
public bool FeatureEnabled { get; private set; }
public DateTime FeatureEnabledTime { get; private set; }
ScheduledEvent FeatureEnableEvent;
const string FeatureEnableEventName = "EnableRoomOnToDefaultSourceWhenOccupied";
public DateTime FeatureDisabledTime { get; private set; }
ScheduledEvent FeatureDisableEvent;
const string FeatureDisableEventName = "DisableRoomOnToDefaultSourceWhenOccupied";
ScheduledEventGroup FeatureEventGroup;
public EssentialsRoomBase Room { get; private set; }
private Fusion.EssentialsHuddleSpaceFusionSystemControllerBase FusionRoom;
public RoomOnToDefaultSourceWhenOccupied(DeviceConfig config) :
base (config)
{
PropertiesConfig = JsonConvert.DeserializeObject<RoomOnToDefaultSourceWhenOccupiedConfig>(config.Properties.ToString());
FeatureEventGroup = new ScheduledEventGroup(this.Key);
FeatureEventGroup.RetrieveAllEvents();
// Add to the global class for tracking
Scheduler.AddEventGroup(FeatureEventGroup);
AddPostActivationAction(() =>
{
// Subscribe to room event to know when RoomOccupancy is set and ready to be subscribed to
if (Room != null)
Room.RoomOccupancyIsSet += new EventHandler<EventArgs>(RoomOccupancyIsSet);
else
Debug.Console(1, this, "Room has no RoomOccupancy object set");
var fusionRoomKey = PropertiesConfig.RoomKey + "-fusion";
FusionRoom = DeviceManager.GetDeviceForKey(fusionRoomKey) as Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase;
if (FusionRoom == null)
Debug.Console(1, this, "Unable to get Fusion Room from Device Manager with key: {0}", fusionRoomKey);
});
}
public override bool CustomActivate()
{
SetUpDevice();
return base.CustomActivate();
}
/// <summary>
/// Sets up device based on config values
/// </summary>
void SetUpDevice()
{
Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as EssentialsRoomBase;
if (Room != null)
{
try
{
FeatureEnabledTime = DateTime.Parse(PropertiesConfig.OccupancyStartTime);
if (FeatureEnabledTime != null)
{
Debug.Console(1, this, "Enabled Time: {0}", FeatureEnabledTime.ToString());
}
else
Debug.Console(1, this, "Unable to parse {0} to DateTime", PropertiesConfig.OccupancyStartTime);
}
catch (Exception e)
{
Debug.Console(1, this, "Unable to parse OccupancyStartTime property: {0} \n Error: {1}", PropertiesConfig.OccupancyStartTime, e);
}
try
{
FeatureDisabledTime = DateTime.Parse(PropertiesConfig.OccupancyEndTime);
if (FeatureDisabledTime != null)
{
Debug.Console(1, this, "Disabled Time: {0}", FeatureDisabledTime.ToString());
}
else
Debug.Console(1, this, "Unable to parse {0} to DateTime", PropertiesConfig.OccupancyEndTime);
}
catch (Exception e)
{
Debug.Console(1, this, "Unable to parse a DateTime config value \n Error: {1}", e);
}
if (!PropertiesConfig.EnableRoomOnWhenOccupied)
FeatureEventGroup.ClearAllEvents();
else
{
AddEnableEventToGroup();
AddDisableEventToGroup();
FeatureEventGroup.UserGroupCallBack += new ScheduledEventGroup.UserEventGroupCallBack(FeatureEventGroup_UserGroupCallBack);
FeatureEventGroup.EnableAllEvents();
}
FeatureEnabled = CheckIfFeatureShouldBeEnabled();
}
else
Debug.Console(1, this, "Unable to get room from Device Manager with key: {0}", PropertiesConfig.RoomKey);
}
protected override void CustomSetConfig(DeviceConfig config)
{
var newPropertiesConfig = JsonConvert.DeserializeObject<RoomOnToDefaultSourceWhenOccupiedConfig>(config.Properties.ToString());
if(newPropertiesConfig != null)
PropertiesConfig = newPropertiesConfig;
ConfigWriter.UpdateDeviceConfig(config);
SetUpDevice();
}
/// <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)
{
if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration)
{
if (SchEvent.Name == FeatureEnableEventName)
{
if (PropertiesConfig.EnableRoomOnWhenOccupied)
FeatureEnabled = true;
Debug.Console(1, this, "*****Feature Enabled by event.*****");
}
else if (SchEvent.Name == FeatureDisableEventName)
{
FeatureEnabled = false;
Debug.Console(1, this, "*****Feature Disabled by event.*****");
}
}
}
/// <summary>
/// Checks if the feature should be currently enabled. Used on startup if processor starts after start time but before end time
/// </summary>
/// <returns></returns>
bool CheckIfFeatureShouldBeEnabled()
{
bool enabled = false;
if(PropertiesConfig.EnableRoomOnWhenOccupied)
{
Debug.Console(1, this, "Current Time: {0} \n FeatureEnabledTime: {1} \n FeatureDisabledTime: {2}", DateTime.Now, FeatureEnabledTime, FeatureDisabledTime);
if (DateTime.Now.TimeOfDay.CompareTo(FeatureEnabledTime.TimeOfDay) >= 0 && FeatureDisabledTime.TimeOfDay.CompareTo(DateTime.Now.TimeOfDay) > 0)
{
if (SchedulerUtilities.CheckIfDayOfWeekMatchesRecurrenceDays(DateTime.Now, CalculateDaysOfWeekRecurrence()))
{
enabled = true;
}
}
}
if(enabled)
Debug.Console(1, this, "*****Feature Enabled*****");
else
Debug.Console(1, this, "*****Feature Disabled*****");
return enabled;
}
/// <summary>
/// Respond to Occupancy status event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void RoomIsOccupiedFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
Debug.Console(1, this, "RoomIsOccupiedFeeback.OutputChange event fired. e.BoolValue: {0}", e.BoolValue);
if(e.BoolValue)
{
// Occupancy detected
if (FeatureEnabled)
{
// Check room power state first
if (!Room.OnFeedback.BoolValue)
{
Debug.Console(1, this, "Powering Room on to default source");
Room.RunDefaultPresentRoute();
}
}
}
}
void CreateEvent(ScheduledEvent schEvent, string name)
{
Debug.Console(1, this, "Adding Event: '{0}'", name);
// Create the event
if (schEvent == null)
schEvent = new ScheduledEvent(name, FeatureEventGroup);
// Set up its initial properties
if(!schEvent.Acknowledgeable)
schEvent.Acknowledgeable = true;
if(!schEvent.Persistent)
schEvent.Persistent = true;
schEvent.DateAndTime.SetFirstDayOfWeek(ScheduledEventCommon.eFirstDayOfWeek.Sunday);
// Set config driven properties
if (schEvent.Name == FeatureEnableEventName)
{
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
if (DateTime.Now.CompareTo(FeatureEnabledTime) > 0)
eventTime = FeatureEnabledTime.AddDays(1);
else
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());
CalculateAndSetAcknowledgeExpirationTimeout(schEvent, FeatureEnabledTime, FeatureDisabledTime);
schEvent.Recurrence.Weekly(eventRecurrennce);
}
else if (schEvent.Name == FeatureDisableEventName)
{
schEvent.Description = "Disables the RoomOnToDefaultSourceWhenOccupiedFeature";
// Check to make sure the date for this event is in the future
if (DateTime.Now.CompareTo(FeatureDisabledTime) > 0)
schEvent.DateAndTime.SetAbsoluteEventTime(FeatureDisabledTime.AddDays(1));
else
schEvent.DateAndTime.SetAbsoluteEventTime(FeatureDisabledTime);
Debug.Console(1, this, "Event '{0}' Absolute time set to {1}", schEvent.Name, schEvent.DateAndTime.ToString());
CalculateAndSetAcknowledgeExpirationTimeout(schEvent, FeatureDisabledTime, FeatureEnabledTime);
schEvent.Recurrence.Daily();
}
}
void CalculateAndSetAcknowledgeExpirationTimeout(ScheduledEvent schEvent, DateTime time1, DateTime time2)
{
Debug.Console(1, this, "time1.Hour = {0}", time1.Hour);
Debug.Console(1, this, "time2.Hour = {0}", time2.Hour);
Debug.Console(1, this, "time1.Minute = {0}", time1.Minute);
Debug.Console(1, this, "time2.Minute = {0}", time2.Minute);
// Calculate the Acknowledge Expiration timer to be the time between the enable and dispable events, less one minute
var ackHours = time2.Hour - time1.Hour;
if(ackHours < 0)
ackHours = ackHours + 24;
var ackMinutes = time2.Minute - time1.Minute;
Debug.Console(1, this, "ackHours = {0}, ackMinutes = {1}", ackHours, ackMinutes);
var ackTotalMinutes = ((ackHours * 60) + ackMinutes) - 1;
var ackExpHour = ackTotalMinutes / 60;
var ackExpMinutes = ackTotalMinutes % 60;
Debug.Console(1, this, "Acknowledge Expiration Timeout: {0} hours, {1} minutes", ackExpHour, ackExpMinutes);
schEvent.AcknowledgeExpirationTimeout.Hour = (ushort)(ackHours);
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>
/// Adds the Enable event to the local event group and sets its properties based on config
/// </summary>
void AddEnableEventToGroup()
{
if (!FeatureEventGroup.ScheduledEvents.ContainsKey(FeatureEnableEventName))
{
CreateEvent(FeatureEnableEvent, FeatureEnableEventName);
}
else
{
// Check if existing event has same time and recurrence as config values
FeatureEnableEvent = FeatureEventGroup.ScheduledEvents[FeatureEnableEventName];
Debug.Console(1, this, "Enable event already found in group");
// 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);
}
}
}
/// <summary>
/// Adds the Enable event to the local event group and sets its properties based on config
/// </summary>
void AddDisableEventToGroup()
{
if (!FeatureEventGroup.ScheduledEvents.ContainsKey(FeatureDisableEventName))
{
CreateEvent(FeatureDisableEvent, FeatureDisableEventName);
}
else
{
FeatureDisableEvent = FeatureEventGroup.ScheduledEvents[FeatureDisableEventName];
Debug.Console(1, this, "Disable event already found in group");
// 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>
/// Calculates the correct bitfield enum value for the event recurrence based on the config values
/// </summary>
/// <returns></returns>
ScheduledEventCommon.eWeekDays CalculateDaysOfWeekRecurrence()
{
ScheduledEventCommon.eWeekDays value = new ScheduledEventCommon.eWeekDays();
if (PropertiesConfig.EnableSunday)
value = value | ScheduledEventCommon.eWeekDays.Sunday;
if (PropertiesConfig.EnableMonday)
value = value | ScheduledEventCommon.eWeekDays.Monday;
if (PropertiesConfig.EnableTuesday)
value = value | ScheduledEventCommon.eWeekDays.Tuesday;
if (PropertiesConfig.EnableWednesday)
value = value | ScheduledEventCommon.eWeekDays.Wednesday;
if (PropertiesConfig.EnableThursday)
value = value | ScheduledEventCommon.eWeekDays.Thursday;
if (PropertiesConfig.EnableFriday)
value = value | ScheduledEventCommon.eWeekDays.Friday;
if (PropertiesConfig.EnableSaturday)
value = value | ScheduledEventCommon.eWeekDays.Saturday;
return value;
}
/// <summary>
/// Callback for event that enables feature. Enables feature if config property is true
/// </summary>
/// <param name="SchEvent"></param>
/// <param name="type"></param>
void FeatureEnableEvent_UserCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type)
{
if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration)
{
if(PropertiesConfig.EnableRoomOnWhenOccupied)
FeatureEnabled = true;
Debug.Console(1, this, "RoomOnToDefaultSourceWhenOccupied Feature Enabled.");
}
}
/// <summary>
/// Callback for event that enables feature. Disables feature
/// </summary>
/// <param name="SchEvent"></param>
/// <param name="type"></param>
void FeatureDisableEvent_UserCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type)
{
if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration)
{
FeatureEnabled = false;
Debug.Console(1, this, "RoomOnToDefaultSourceWhenOccupied Feature Disabled.");
}
}
}
public class RoomOnToDefaultSourceWhenOccupiedConfig
{
[JsonProperty("roomKey")]
public string RoomKey { get; set; }
[JsonProperty("enableRoomOnWhenOccupied")]
public bool EnableRoomOnWhenOccupied { get; set; }
[JsonProperty("occupancyStartTime")]
public string OccupancyStartTime { get; set; }
[JsonProperty("occupancyEndTime")]
public string OccupancyEndTime { get; set; }
[JsonProperty("enableSunday")]
public bool EnableSunday { get; set; }
[JsonProperty("enableMonday")]
public bool EnableMonday { get; set; }
[JsonProperty("enableTuesday")]
public bool EnableTuesday { get; set; }
[JsonProperty("enableWednesday")]
public bool EnableWednesday { get; set; }
[JsonProperty("enableThursday")]
public bool EnableThursday { get; set; }
[JsonProperty("enableFriday")]
public bool EnableFriday { get; set; }
[JsonProperty("enableSaturday")]
public bool EnableSaturday { get; set; }
}
}

View File

@@ -0,0 +1,311 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.Scheduler;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Devices;
namespace PepperDash.Essentials.Core
{
/// <summary>
///
/// </summary>
public abstract class EssentialsRoomBase : ReconfigurableDevice
{
/// <summary>
///
/// </summary>
public BoolFeedback OnFeedback { get; private set; }
/// <summary>
/// Fires when the RoomOccupancy object is set
/// </summary>
public event EventHandler<EventArgs> RoomOccupancyIsSet;
public BoolFeedback IsWarmingUpFeedback { get; private set; }
public BoolFeedback IsCoolingDownFeedback { get; private set; }
public IOccupancyStatusProvider RoomOccupancy { get; private set; }
public bool OccupancyStatusProviderIsRemote { get; private set; }
protected abstract Func<bool> IsWarmingFeedbackFunc { get; }
protected abstract Func<bool> IsCoolingFeedbackFunc { get; }
/// <summary>
/// The config name of the source list
/// </summary>
public string SourceListKey { get; set; }
/// <summary>
/// Timer used for informing the UIs of a shutdown
/// </summary>
public SecondsCountdownTimer ShutdownPromptTimer { get; private set; }
/// <summary>
///
/// </summary>
public int ShutdownPromptSeconds { get; set; }
public int ShutdownVacancySeconds { get; set; }
public eShutdownType ShutdownType { get; private set; }
public EssentialsRoomEmergencyBase Emergency { get; set; }
public Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; set; }
public string LogoUrl { get; set; }
protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; }
public eVacancyMode VacancyMode { get; private set; }
/// <summary>
/// Seconds after vacancy prompt is displayed until shutdown
/// </summary>
protected int RoomVacancyShutdownSeconds;
/// <summary>
/// Seconds after vacancy detected until prompt is displayed
/// </summary>
protected int RoomVacancyShutdownPromptSeconds;
/// <summary>
///
/// </summary>
protected abstract Func<bool> OnFeedbackFunc { get; }
protected Dictionary<IBasicVolumeWithFeedback, uint> SavedVolumeLevels = new Dictionary<IBasicVolumeWithFeedback, uint>();
/// <summary>
/// When volume control devices change, should we zero the one that we are leaving?
/// </summary>
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; }
public EssentialsRoomBase(DeviceConfig config)
: base(config)
{
// Setup the ShutdownPromptTimer
ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer");
ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) =>
{
if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue)
ShutdownType = eShutdownType.None;
};
ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered
ShutdownPromptSeconds = 60;
ShutdownVacancySeconds = 120;
ShutdownType = eShutdownType.None;
RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer");
//RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) =>
//{
// if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue)
// ShutdownType = ShutdownType.Vacancy;
//};
RoomVacancyShutdownTimer.HasFinished += new EventHandler<EventArgs>(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered
RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning
RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt
VacancyMode = eVacancyMode.None;
OnFeedback = new BoolFeedback(OnFeedbackFunc);
IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc);
IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc);
AddPostActivationAction(() =>
{
if (RoomOccupancy != null)
OnRoomOccupancyIsSet();
});
}
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();
Debug.Console(0, this, "ShutdwonPromptTimer Started. Type: {0}. Seconds: {1}", ShutdownType, ShutdownPromptTimer.SecondsToCount);
}
public void StartRoomVacancyTimer(eVacancyMode mode)
{
if (mode == eVacancyMode.None)
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds;
else if (mode == eVacancyMode.InInitialVacancy)
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds;
VacancyMode = mode;
RoomVacancyShutdownTimer.Start();
Debug.Console(0, this, "Vacancy Timer Started. Mode: {0}. Seconds: {1}", VacancyMode, RoomVacancyShutdownTimer.SecondsToCount);
}
/// <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 Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase)
OccupancyStatusProviderIsRemote = true;
if(timeoutMinutes > 0)
RoomVacancyShutdownSeconds = timeoutMinutes * 60;
Debug.Console(1, this, "RoomVacancyShutdownSeconds set to {0}", RoomVacancyShutdownSeconds);
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>
/// To allow base class to power room on to default source
/// </summary>
/// <returns></returns>
public abstract bool RunDefaultPresentRoute();
void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
{
if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false)
{
Debug.Console(1, this, "Notice: Vacancy Detected");
// Trigger the timer when the room is vacant
StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
}
else
{
Debug.Console(1, this, "Notice: Occupancy Detected");
// Reset the timer when the room is occupied
RoomVacancyShutdownTimer.Cancel();
}
}
/// <summary>
/// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed
/// </summary>
/// <param name="o"></param>
public abstract void RoomVacatedForTimeoutPeriod(object o);
}
/// <summary>
/// To describe the various ways a room may be shutting down
/// </summary>
public enum eShutdownType
{
None = 0,
External,
Manual,
Vacancy
}
public enum eVacancyMode
{
None = 0,
InInitialVacancy,
InShutdownWarning
}
/// <summary>
///
/// </summary>
public enum eWarmingCoolingMode
{
None,
Warming,
Cooling
}
public abstract class EssentialsRoomEmergencyBase : IKeyed
{
public string Key { get; private set; }
public EssentialsRoomEmergencyBase(string key)
{
Key = key;
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// For rooms with routing
/// </summary>
public interface IRunRouteAction
{
void RunRouteAction(string routeKey);
void RunRouteAction(string routeKey, Action successCallback);
}
/// <summary>
/// For rooms that default presentation only routing
/// </summary>
public interface IRunDefaultPresentRoute
{
bool RunDefaultPresentRoute();
}
/// <summary>
/// For rooms that have default presentation and calling routes
/// </summary>
public interface IRunDefaultCallRoute : IRunDefaultPresentRoute
{
bool RunDefaultCallRoute();
}
}

View File

@@ -1,41 +0,0 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using Crestron.SimplSharp;
//namespace PepperDash.Essentials.Core
//{
// public class EssentialsRoomSourceChangeEventArgs : EventArgs
// {
// public EssentialsRoom Room { get; private set; }
// public IPresentationSource OldSource { get; private set; }
// public IPresentationSource NewSource { get; private set; }
// public EssentialsRoomSourceChangeEventArgs(EssentialsRoom room,
// IPresentationSource oldSource, IPresentationSource newSource)
// {
// Room = room;
// OldSource = oldSource;
// NewSource = newSource;
// }
// }
// public class EssentialsRoomAudioDeviceChangeEventArgs : EventArgs
// {
// public EssentialsRoom Room { get; private set; }
// public IBasicVolumeControls OldDevice { get; private set; }
// public IBasicVolumeControls NewDevice { get; private set; }
// public EssentialsRoomAudioDeviceChangeEventArgs(EssentialsRoom room,
// IBasicVolumeControls oldDevice, IBasicVolumeControls newDevice)
// {
// Room = room;
// OldDevice = oldDevice;
// NewDevice = newDevice;
// }
// }
//}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Core
{
public interface IOccupancyStatusProvider
{
BoolFeedback RoomIsOccupiedFeedback { get; }
}
}