Merge remote-tracking branch 'origin/feature/ecs-342' into feature/ecs-500

This commit is contained in:
Heath Volmer
2017-10-05 16:18:47 -06:00
17 changed files with 608 additions and 98 deletions

View File

@@ -1,56 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
//***************************************************************************************************
public abstract class Room : Device, IHasFeedback
{
public abstract BoolFeedback RoomIsOnFeedback { get; protected set; }
public abstract BoolFeedback IsCoolingDownFeedback { get; protected set; }
public abstract BoolFeedback IsWarmingUpFeedback { get; protected set; }
// In concrete classes, these should be computed from the relevant devices
public virtual uint CooldownTime { get { return 10000; } }
public virtual uint WarmupTime { get { return 5000; } }
public string Description { get; set; }
public string HelpMessage { get; set; }
public Room(string key, string name)
: base(key, name)
{
Description = "";
HelpMessage = "";
}
public virtual void RoomOn() { }
public virtual void RoomOff() { }
#region IDeviceWithOutputs Members
public virtual List<Feedback> Feedbacks
{
get
{
return new List<Feedback>
{
RoomIsOnFeedback,
IsCoolingDownFeedback,
IsWarmingUpFeedback
};
}
}
#endregion
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
//***************************************************************************************************
public abstract class Room : Device, IHasFeedback
{
public abstract BoolFeedback RoomIsOnFeedback { get; protected set; }
public abstract BoolFeedback IsCoolingDownFeedback { get; protected set; }
public abstract BoolFeedback IsWarmingUpFeedback { get; protected set; }
// In concrete classes, these should be computed from the relevant devices
public virtual uint CooldownTime { get { return 10000; } }
public virtual uint WarmupTime { get { return 5000; } }
public string Description { get; set; }
public string HelpMessage { get; set; }
public Room(string key, string name)
: base(key, name)
{
Description = "";
HelpMessage = "";
}
public virtual void RoomOn() { }
public virtual void RoomOff() { }
#region IDeviceWithOutputs Members
public virtual List<Feedback> Feedbacks
{
get
{
return new List<Feedback>
{
RoomIsOnFeedback,
IsCoolingDownFeedback,
IsWarmingUpFeedback
};
}
}
#endregion
}
}

View File

@@ -6,6 +6,15 @@ using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.Codec
{
public enum eMeetingEventChangeType
{
Unkown = 0,
MeetingStartWarning,
MeetingStart,
MeetingEndWarning,
MeetingEnd
}
public interface IHasScheduleAwareness
{
CodecScheduleAwareness CodecSchedule { get; }
@@ -13,11 +22,70 @@ namespace PepperDash.Essentials.Devices.Common.Codec
public class CodecScheduleAwareness
{
public List<Meeting> Meetings { get; set; }
List<Meeting> _Meetings;
public event EventHandler<MeetingEventArgs> MeetingEventChange;
public event EventHandler<EventArgs> MeetingsListHasChanged;
public List<Meeting> Meetings
{
get
{
return _Meetings;
}
set
{
_Meetings = value;
var handler = MeetingsListHasChanged;
if (handler != null)
{
handler(this, new EventArgs());
}
}
}
private CTimer ScheduleChecker;
public CodecScheduleAwareness()
{
Meetings = new List<Meeting>();
ScheduleChecker = new CTimer(CheckSchedule, null, 1000, 1000);
}
private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting)
{
var handler = MeetingEventChange;
if (handler != null)
{
handler(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting });
}
}
private void CheckSchedule(object o)
{
// Iterate the meeting list and check if any meeting need to do anythingk
foreach (Meeting m in Meetings)
{
eMeetingEventChangeType changeType = eMeetingEventChangeType.Unkown;
if (m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes) // Meeting is about to start
changeType = eMeetingEventChangeType.MeetingStartWarning;
else if (m.TimeToMeetingStart.TotalMinutes == 0) // Meeting Start
changeType = eMeetingEventChangeType.MeetingStart;
else if (m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes) // Meeting is about to end
changeType = eMeetingEventChangeType.MeetingEndWarning;
else if (m.TimeToMeetingEnd.TotalMinutes == 0) // Meeting has ended
changeType = eMeetingEventChangeType.MeetingEnd;
if (changeType != eMeetingEventChangeType.Unkown)
OnMeetingChange(changeType, m);
}
}
}
@@ -26,10 +94,26 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public class Meeting
{
public TimeSpan MeetingWarningMinutes = TimeSpan.FromMinutes(5);
public string Id { get; set; }
public string Organizer { get; set; }
public string Title { get; set; }
public string Agenda { get; set; }
public TimeSpan TimeToMeetingStart
{
get
{
return StartTime - DateTime.Now;
}
}
public TimeSpan TimeToMeetingEnd
{
get
{
return EndTime - DateTime.Now;
}
}
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public TimeSpan Duration
@@ -44,11 +128,18 @@ namespace PepperDash.Essentials.Devices.Common.Codec
{
get
{
return StartTime.AddMinutes(-5) <= DateTime.Now
&& DateTime.Now <= EndTime.AddMinutes(-5);
return StartTime.AddMinutes(-5) <= DateTime.Now
&& DateTime.Now <= EndTime.AddMinutes(-5);
}
}
public string ConferenceNumberToDial { get; set; }
public string ConferencePassword { get; set; }
}
}
public class MeetingEventArgs : EventArgs
{
public eMeetingEventChangeType ChangeType { get; set; }
public Meeting Meeting { get; set; }
}
}

View File

@@ -130,6 +130,9 @@
<Compile Include="DSP\PolycomSoundStructure\SoundStructureBasics.cs" />
<Compile Include="Factory\DeviceFactory.cs" />
<Compile Include="Generic\GenericSource.cs" />
<Compile Include="Occupancy\EssentialsGlsOccupancySensorBaseController.cs" />
<Compile Include="Occupancy\EssentialsOccupancyAggregator.cs" />
<Compile Include="Occupancy\iOccupancyStatusProvider.cs" />
<Compile Include="PC\InRoomPc.cs" />
<Compile Include="PC\Laptop.cs" />
<Compile Include="SetTopBox\SetTopBoxPropertiesConfig.cs" />
@@ -149,6 +152,8 @@
<Compile Include="VideoCodec\CiscoCodec\xEvent.cs" />
<Compile Include="VideoCodec\CiscoCodec\HttpApiServer.cs" />
<Compile Include="Codec\CodecActiveCallItem.cs" />
<Compile Include="VideoCodec\Interfaces\IHasCodecLayouts.cs" />
<Compile Include="VideoCodec\Interfaces\IHasCodecSelfview.cs" />
<Compile Include="VideoCodec\MockVC\MockVC.cs" />
<Compile Include="VideoCodec\CiscoCodec\xStatus.cs" />
<Compile Include="VideoCodec\VideoCodecBase.cs" />

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.GeneralIO;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Occupancy
{
public class EssentialsGlsOccupancySensorBaseController : CrestronGenericBaseDevice, IOccupancyStatusProvider
{
public GlsOccupancySensorBase OccSensor { get; private set; }
public BoolFeedback RoomIsOccupiedFeedback { get; private set; }
public EssentialsGlsOccupancySensorBaseController(string key, string name, GlsOccupancySensorBase sensor, GlsOccupancySensorConfigurationProperties props)
: base(key, name, sensor)
{
}
}
public class GlsOccupancySensorConfigurationProperties
{
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Occupancy
{
/// <summary>
/// Aggregates the RoomIsOccupied feedbacks of one or more IOccupancyStatusProvider objects
/// </summary>
public class EssentialsOccupancyAggregator : Device, IOccupancyStatusProvider
{
/// <summary>
/// Aggregated feedback of all linked IOccupancyStatusProvider devices
/// </summary>
public BoolFeedback RoomIsOccupiedFeedback
{
get
{
return AggregatedOccupancyStatus.Output;
}
}
private BoolFeedbackOr AggregatedOccupancyStatus;
public EssentialsOccupancyAggregator(string key, string name)
: base(key, name)
{
AggregatedOccupancyStatus = new BoolFeedbackOr();
}
/// <summary>
/// Adds an IOccupancyStatusProvider device
/// </summary>
/// <param name="statusProvider"></param>
public void AddOccupancyStatusProvider(IOccupancyStatusProvider statusProvider)
{
AggregatedOccupancyStatus.AddOutputIn(statusProvider.RoomIsOccupiedFeedback);
}
}
}

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.Devices.Common.Occupancy
{
public interface IOccupancyStatusProvider
{
BoolFeedback RoomIsOccupiedFeedback { get; }
}
}

View File

@@ -288,8 +288,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
meetings.OrderBy(m => m.StartTime);
return meetings;
}
}

View File

@@ -6,6 +6,7 @@ using Crestron.SimplSharp;
using Crestron.SimplSharp.Net.Https;
using Crestron.SimplSharp.CrestronXml;
using Crestron.SimplSharp.CrestronXml.Serialization;
//using Crestron.SimplSharpPro;
using Newtonsoft.Json;
using Cisco_One_Button_To_Push;
using Cisco_SX80_Corporate_Phone_Book;
@@ -14,13 +15,14 @@ using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Routing;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.Occupancy;
using PepperDash.Essentials.Devices.Common.VideoCodec;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
enum eCommandType { SessionStart, SessionEnd, Command, GetStatus, GetConfiguration };
public class CiscoCodec : VideoCodecBase, IHasCallHistory, IHasCallFavorites, IHasDirectory, IHasScheduleAwareness
public class CiscoCodec : VideoCodecBase, IHasCallHistory, IHasCallFavorites, IHasDirectory, IHasScheduleAwareness, IOccupancyStatusProvider, IHasCodecLayouts, IHasCodecSelfview
{
public event EventHandler<DirectoryEventArgs> DirectoryResultReturned;
@@ -38,16 +40,47 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public BoolFeedback SpeakerTrackIsOnFeedback { get; private set; }
//private CiscoOneButtonToPush CodecObtp;
public BoolFeedback SelfviewIsOnFeedback { get; private set; }
//private Corporate_Phone_Book PhoneBook;
public StringFeedback SelfviewPipPositionFeedback { get; private set; }
public StringFeedback LocalLayoutFeedback { get; private set; }
private CodecCommandWithLabel CurrentSelfviewPipPosition;
private CodecCommandWithLabel CurrentLocalLayout;
/// <summary>
/// List the available positions for the selfview PIP window
/// </summary>
public List<CodecCommandWithLabel> SelfviewPipPositions = new List<CodecCommandWithLabel>()
{
new CodecCommandWithLabel("CenterLeft", "Center Left"),
new CodecCommandWithLabel("CenterRight", "Center Right"),
new CodecCommandWithLabel("LowerLeft", "Lower Left"),
new CodecCommandWithLabel("LowerRight", "Lower Right"),
new CodecCommandWithLabel("UpperCenter", "Upper Center"),
new CodecCommandWithLabel("UpperLeft", "Upper Left"),
new CodecCommandWithLabel("UpperRight", "Upper Right"),
};
/// <summary>
/// Lists the available options for local layout
/// </summary>
public List<CodecCommandWithLabel> LocalLayouts = new List<CodecCommandWithLabel>()
{
new CodecCommandWithLabel("auto", "Auto"),
//new CiscoCodecLocalLayout("custom", "Custom"), // Left out for now
new CodecCommandWithLabel("equal","Equal"),
new CodecCommandWithLabel("overlay","Overlay"),
new CodecCommandWithLabel("prominent","Prominent"),
new CodecCommandWithLabel("single","Single")
};
private CiscoCodecConfiguration.RootObject CodecConfiguration;
private CiscoCodecStatus.RootObject CodecStatus;
//private CiscoCodecPhonebook.RootObject CodecPhonebook;
public CodecCallHistory CallHistory { get; private set; }
public CodecCallFavorites CallFavorites { get; private set; }
@@ -127,22 +160,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
}
}
//protected override Func<int> ActiveCallCountFeedbackFunc
//{
// get { return () => ActiveCalls.Count; }
//}
protected Func<bool> SelfViewIsOnFeedbackFunc
{
get
{
return () => CodecStatus.Status.Video.Selfview.Mode.BoolValue;
}
}
//private HttpsClient Client;
protected Func<string> SelfviewPipPositionFeedbackFunc
{
get
{
return () => CurrentSelfviewPipPosition.Label;
}
}
//private HttpApiServer Server;
//private int ServerPort;
//private string CodecUrl;
//private string HttpSessionId;
//private string FeedbackRegistrationExpression;
protected Func<string> LocalLayoutFeedbackFunc
{
get
{
return () => CurrentLocalLayout.Label;
}
}
private string CliFeedbackRegistrationExpression;
@@ -181,6 +221,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
RoomIsOccupiedFeedback = new BoolFeedback(RoomIsOccupiedFeedbackFunc);
PeopleCountFeedback = new IntFeedback(PeopleCountFeedbackFunc);
SpeakerTrackIsOnFeedback = new BoolFeedback(SpeakerTrackIsOnFeedbackFunc);
SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc);
SelfviewPipPositionFeedback = new StringFeedback(SelfviewPipPositionFeedbackFunc);
LocalLayoutFeedback = new StringFeedback(LocalLayoutFeedbackFunc);
Communication = comm;
@@ -220,8 +263,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CallHistory = new CodecCallHistory();
CallFavorites = new CodecCallFavorites();
CallFavorites.Favorites = props.Favorites;
if (props.Favorites != null)
{
CallFavorites = new CodecCallFavorites();
CallFavorites.Favorites = props.Favorites;
}
DirectoryRoot = new CodecDirectory();
@@ -235,6 +281,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CodecStatus.Status.RoomAnalytics.PeoplePresence.ValueChangedAction = RoomIsOccupiedFeedback.FireUpdate;
CodecStatus.Status.RoomAnalytics.PeopleCount.Current.ValueChangedAction = PeopleCountFeedback.FireUpdate;
CodecStatus.Status.Cameras.SpeakerTrack.Status.ValueChangedAction = SpeakerTrackIsOnFeedback.FireUpdate;
CodecStatus.Status.Video.Selfview.Mode.ValueChangedAction = SelfviewIsOnFeedback.FireUpdate;
CodecStatus.Status.Video.Selfview.PIPPosition.ValueChangedAction = ComputeSelfviewPipStatus;
CodecStatus.Status.Video.Layout.LayoutFamily.Local.ValueChangedAction = ComputeLocalLayout;
}
/// <summary>
@@ -628,6 +677,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
JsonConvert.PopulateObject(response, codecBookings);
CodecSchedule.Meetings = CiscoCodecBookings.GetGenericMeetingsFromBookingResult(codecBookings.CommandResponse.BookingsListResult.Booking);
}
}
@@ -939,6 +990,109 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
SendText("xCommand SystemUnit Boot Action: Restart");
}
/// <summary>
/// Turns on Selfview Mode
/// </summary>
public void SelfviewModeOn()
{
SendText("xCommand Video Selfview Set Mode: On");
}
/// <summary>
/// Turns off Selfview Mode
/// </summary>
public void SelfviewModeOff()
{
SendText("xCommand Video Selfview Set Mode: Off");
}
/// <summary>
/// Toggles Selfview mode on/off
/// </summary>
public void SelfviewModeToggle()
{
string mode = string.Empty;
if (CodecStatus.Status.Video.Selfview.Mode.BoolValue)
mode = "Off";
else
mode = "On";
SendText(string.Format("xCommand Video Selfview Set Mode: {0}", mode));
}
/// <summary>
/// Sets a specified position for the selfview PIP window
/// </summary>
/// <param name="position"></param>
public void SelfviewPipPositionSet(CodecCommandWithLabel position)
{
SendText(string.Format("xCommand Video Selfview Set Mode: On PIPPosition: {0}", position.Command));
}
/// <summary>
/// Toggles to the next selfview PIP position
/// </summary>
public void SelfviewPipPositionToggle()
{
if (CurrentSelfviewPipPosition != null)
{
var nextPipPositionIndex = SelfviewPipPositions.IndexOf(CurrentSelfviewPipPosition) + 1;
if (nextPipPositionIndex >= SelfviewPipPositions.Count) // Check if we need to loop back to the first item in the list
nextPipPositionIndex = 0;
SelfviewPipPositionSet(SelfviewPipPositions[nextPipPositionIndex]);
}
}
/// <summary>
/// Sets a specific local layout
/// </summary>
/// <param name="layout"></param>
public void LocalLayoutSet(CodecCommandWithLabel layout)
{
SendText(string.Format("xCommand Video Layout LayoutFamily Set Target: local LayoutFamily: {0}", layout.Command));
}
/// <summary>
/// Toggles to the next local layout
/// </summary>
public void LocalLayoutToggle()
{
if(CurrentLocalLayout != null)
{
var nextLocalLayoutIndex = LocalLayouts.IndexOf(CurrentLocalLayout) + 1;
if (nextLocalLayoutIndex >= LocalLayouts.Count) // Check if we need to loop back to the first item in the list
nextLocalLayoutIndex = 0;
LocalLayoutSet(LocalLayouts[nextLocalLayoutIndex]);
}
}
/// <summary>
/// Calculates the current selfview PIP position
/// </summary>
void ComputeSelfviewPipStatus()
{
CurrentSelfviewPipPosition = SelfviewPipPositions.FirstOrDefault(p => p.Command.ToLower().Equals(CodecStatus.Status.Video.Selfview.PIPPosition.Value.ToLower()));
if(CurrentSelfviewPipPosition != null)
SelfviewIsOnFeedback.FireUpdate();
}
/// <summary>
/// Calculates the current local Layout
/// </summary>
void ComputeLocalLayout()
{
CurrentLocalLayout = LocalLayouts.FirstOrDefault(l => l.Command.ToLower().Equals(CodecStatus.Status.Video.Layout.LayoutFamily.Local.Value.ToLower()));
if (CurrentLocalLayout != null)
LocalLayoutFeedback.FireUpdate();
}
public void RemoveCallHistoryEntry(CodecCallHistory.CallHistoryEntry entry)
{
SendText(string.Format("xCommand CallHistory DeleteEntry CallHistoryId: {0} AcknowledgeConsecutiveDuplicates: True", entry.OccurrenceHistoryId));
@@ -1012,6 +1166,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
}
}
/// <summary>
/// Represents a codec command that might need to have a friendly label applied for UI feedback purposes
/// </summary>
public class CodecCommandWithLabel
{
public string Command { get; set; }
public string Label { get; set; }
public CodecCommandWithLabel(string command, string label)
{
Command = command;
Label = label;
}
}
/// <summary>
/// Tracks the initial sycnronization state of the codec when making a connection
/// </summary>

View File

@@ -1485,19 +1485,42 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public List<Source> Source { get; set; }
}
public class Local
public class Local : ValueProperty
{
public string Value { get; set; }
string _Value;
public string Value // Valid values are On/Off
{
get
{
return _Value;
}
set
{
_Value = value;
OnValueChanged();
}
}
}
public class LayoutFamily
{
public Local Local { get; set; }
public LayoutFamily()
{
Local = new Local();
}
}
public class Layout
{
public LayoutFamily LayoutFamily { get; set; }
public Layout()
{
LayoutFamily = new LayoutFamily();
}
}
public class Monitors
@@ -1588,19 +1611,43 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public string Value { get; set; }
}
public class Mode8
public class Mode8 : ValueProperty
{
public string Value { get; set; }
public bool BoolValue { get; private set; }
public string Value // Valid values are On/Off
{
set
{
// If the incoming value is "On" it sets the BoolValue true, otherwise sets it false
BoolValue = value == "On";
OnValueChanged();
}
}
}
public class OnMonitorRole
{
public string Value { get; set; }
}
public class PIPPosition3
public class PIPPosition3 : ValueProperty
{
public string Value { get; set; }
string _Value;
public string Value
{
get
{
return _Value;
}
set
{
_Value = value;
OnValueChanged();
}
}
}
public class Selfview
@@ -1609,6 +1656,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Mode8 Mode { get; set; }
public OnMonitorRole OnMonitorRole { get; set; }
public PIPPosition3 PIPPosition { get; set; }
public Selfview()
{
Mode = new Mode8();
PIPPosition = new PIPPosition3();
}
}
public class Video
@@ -1620,6 +1673,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Output2 Output { get; set; }
public Presentation2 Presentation { get; set; }
public Selfview Selfview { get; set; }
public Video()
{
Selfview = new Selfview();
Layout = new Layout();
}
}
public class AnswerState
@@ -1751,6 +1810,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
RoomAnalytics = new RoomAnalytics();
Conference = new Conference2();
SystemUnit = new SystemUnit();
Video = new Video();
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
/// <summary>
/// Defines the required elements for layout control
/// </summary>
public interface IHasCodecLayouts
{
StringFeedback LocalLayoutFeedback { get; }
void LocalLayoutToggle();
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
/// <summary>
/// Defines the requred elements for selfview control
/// </summary>
public interface IHasCodecSelfview
{
BoolFeedback SelfviewIsOnFeedback { get; }
void SelfviewModeOn();
void SelfviewModeOff();
void SelfviewModeToggle();
}
}

View File

@@ -138,7 +138,7 @@
<Compile Include="OTHER\Fusion\FusionProcessorQueries.cs" />
<Compile Include="OTHER\Fusion\FusionRviDataClasses.cs" />
<Compile Include="REMOVE EssentialsApp.cs" />
<Compile Include="OTHER\Fusion\FusionSystemController.cs" />
<Compile Include="OTHER\Fusion\EssentialsHuddleSpaceFusionSystemController.cs" />
<Compile Include="HttpApiHandler.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Room\Config\EssentialsPresentationPropertiesConfig.cs" />

View File

@@ -412,7 +412,12 @@ namespace PepperDash.Essentials
dest.ReleaseAndMakeRoute(source, route.Type);
}
return true;
}
}
public override void RoomVacatedForTimeoutPeriod(object o)
{
//Implement this
}
/// <summary>
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions

View File

@@ -451,7 +451,12 @@ namespace PepperDash.Essentials
dest.ReleaseAndMakeRoute(source, route.Type);
}
return true;
}
}
public override void RoomVacatedForTimeoutPeriod(object o)
{
//Implement this
}
/// <summary>
/// Does what it says

View File

@@ -426,6 +426,12 @@ namespace PepperDash.Essentials
dest.ReleaseAndMakeRoute(source, route.Type);
}
return true;
}
}
public override void RoomVacatedForTimeoutPeriod(object o)
{
//Implement this
}
}
}

View File

@@ -4,7 +4,8 @@ using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Occupancy;
namespace PepperDash.Essentials
{
@@ -16,7 +17,6 @@ namespace PepperDash.Essentials
event SourceInfoChangeHandler CurrentSingleSourceChange;
}
/// <summary>
///
/// </summary>
@@ -28,7 +28,9 @@ namespace PepperDash.Essentials
public BoolFeedback OnFeedback { get; private set; }
public BoolFeedback IsWarmingUpFeedback { get; private set; }
public BoolFeedback IsCoolingDownFeedback { get; private set; }
public BoolFeedback IsCoolingDownFeedback { get; private set; }
public IOccupancyStatusProvider RoomOccupancy { get; private set; }
protected abstract Func<bool> IsWarmingFeedbackFunc { get; }
protected abstract Func<bool> IsCoolingFeedbackFunc { get; }
@@ -47,7 +49,11 @@ namespace PepperDash.Essentials
public PepperDash.Essentials.Room.EssentialsRoomEmergencyBase Emergency { get; set; }
public string LogoUrl { get; set; }
public string LogoUrl { get; set; }
protected CTimer RoomVacancyShutdownTimer;
protected long RoomVacancyShutdownTimeout = 1800000; // 30 minutes by default
/// <summary>
///
@@ -103,9 +109,41 @@ namespace PepperDash.Essentials
/// <summary>
/// Override this to implement a default volume level(s) method
/// </summary>
public abstract void SetDefaultLevels();
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)
{
RoomOccupancy = statusProvider;
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += new EventHandler<EventArgs>(RoomIsOccupiedFeedback_OutputChange);
}
void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
{
if ((sender as IOccupancyStatusProvider).RoomIsOccupiedFeedback.BoolValue == false)
{
// Trigger the timer when the room is vacant
RoomVacancyShutdownTimer = new CTimer(RoomVacatedForTimeoutPeriod, RoomVacancyShutdownTimeout);
}
else
{
// Reset the timer when the room is occupied
if(RoomVacancyShutdownTimer != null)
RoomVacancyShutdownTimer.Reset(RoomVacancyShutdownTimeout);
}
}
/// <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>