From 7de0251188e4a7e824dd4d079b6343b3b3192dd6 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 8 Jun 2021 11:44:09 -0600 Subject: [PATCH 01/14] add ConvertType method to convert type This method should allow for using a string value in place of an enum as a parameter. Integers will still fail. --- .../Devices/DeviceJsonApi.cs | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceJsonApi.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceJsonApi.cs index a1930cf0..2dda0bf8 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceJsonApi.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceJsonApi.cs @@ -77,10 +77,9 @@ namespace PepperDash.Essentials.Core var mParams = method.GetParameters(); var convertedParams = mParams - .Select((p, i) => Convert.ChangeType(action.Params[i], p.ParameterType, - System.Globalization.CultureInfo.InvariantCulture)) + .Select((p, i) => ConvertType(action.Params[i], p.ParameterType)) .ToArray(); - var ret = method.Invoke(obj, convertedParams); + method.Invoke(obj, convertedParams); CrestronConsole.ConsoleCommandResponse("Method {0} successfully called on device {1}", method.Name, action.DeviceKey); @@ -91,6 +90,23 @@ namespace PepperDash.Essentials.Core ex.Message);} } + private static object ConvertType(object value, Type conversionType) + { + if (!conversionType.IsEnum) + { + return Convert.ChangeType(value, conversionType, System.Globalization.CultureInfo.InvariantCulture); + } + + var stringValue = Convert.ToString(value); + + if (String.IsNullOrEmpty(stringValue)) + { + throw new InvalidCastException( + String.Format("{0} cannot be converted to a string prior to conversion to enum")); + } + return Enum.Parse(conversionType, stringValue, true); + } + /// /// Gets the properties on a device /// @@ -275,6 +291,8 @@ namespace PepperDash.Essentials.Core //var props = t.GetProperties().Select(p => new PropertyNameType(p, obj)); //return JsonConvert.SerializeObject(props, Formatting.Indented); } + + } public class DeviceActionWrapper From 1ebacf3f0f50f5d248d9bd73979207bd7b502996 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 8 Jun 2021 12:12:59 -0600 Subject: [PATCH 02/14] Fix formatting issue --- .../PepperDashEssentialsBase/Devices/DeviceManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs index cca16ec7..aac38dfa 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs @@ -435,7 +435,7 @@ namespace PepperDash.Essentials.Core var min = Convert.ToUInt32(timeout); device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, min); - Debug.Console(0, "Device: '{0}' debug level set to {1) for {2} minutes", deviceKey, debugSetting, min); + Debug.Console(0, "Device: '{0}' debug level set to {1} for {2} minutes", deviceKey, debugSetting, min); } catch (Exception e) From a76f4c15dc81dae7789f5155d92e564ab5b27fe3 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 29 Jun 2021 09:47:56 -0600 Subject: [PATCH 03/14] Updates to IHasScheduleAwareness --- .../Codec/iHasScheduleAwareness.cs | 18 ++++++++++++++++++ .../VideoCodec/MockVC/MockVC.cs | 4 +++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs index 7d6acdc2..8799b33b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Text; using Crestron.SimplSharp; +using Newtonsoft.Json; + namespace PepperDash.Essentials.Devices.Common.Codec { public enum eMeetingEventChangeType @@ -115,17 +117,24 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public class Meeting { + [JsonProperty("minutesBeforeMeeting")] public int MinutesBeforeMeeting; + [JsonProperty("id")] public string Id { get; set; } + [JsonProperty("organizer")] public string Organizer { get; set; } + [JsonProperty("title")] public string Title { get; set; } + [JsonProperty("agenda")] public string Agenda { get; set; } + [JsonProperty("meetingWarningMinutes")] public TimeSpan MeetingWarningMinutes { get { return TimeSpan.FromMinutes(MinutesBeforeMeeting); } } + [JsonProperty("timeToMeetingStart")] public TimeSpan TimeToMeetingStart { get @@ -133,6 +142,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec return StartTime - DateTime.Now; } } + [JsonProperty("timeToMeetingEnd")] public TimeSpan TimeToMeetingEnd { get @@ -140,8 +150,11 @@ namespace PepperDash.Essentials.Devices.Common.Codec return EndTime - DateTime.Now; } } + [JsonProperty("startTime")] public DateTime StartTime { get; set; } + [JsonProperty("endTime")] public DateTime EndTime { get; set; } + [JsonProperty("duration")] public TimeSpan Duration { get @@ -149,7 +162,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec return EndTime - StartTime; } } + [JsonProperty("privacy")] public eMeetingPrivacy Privacy { get; set; } + [JsonProperty("joinable")] public bool Joinable { get @@ -159,9 +174,12 @@ namespace PepperDash.Essentials.Devices.Common.Codec } } //public string ConferenceNumberToDial { get; set; } + [JsonProperty("conferencePassword")] public string ConferencePassword { get; set; } + [JsonProperty("isOneButtonToPushMeeting")] public bool IsOneButtonToPushMeeting { get; set; } + [JsonProperty("calls")] public List Calls { get; private set; } public Meeting() diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs index c4bfa298..a947a1d1 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs @@ -396,10 +396,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (_CodecSchedule == null || _CodecSchedule.Meetings.Count == 0 || _CodecSchedule.Meetings[_CodecSchedule.Meetings.Count - 1].StartTime < DateTime.Now) { - _CodecSchedule = new CodecScheduleAwareness(); + _CodecSchedule = new CodecScheduleAwareness(10000); for (int i = 0; i < 5; i++) { var m = new Meeting(); + m.Id = i.ToString(); + m.Organizer = "Employee " + 1; m.StartTime = DateTime.Now.AddMinutes(3).AddHours(i); m.EndTime = DateTime.Now.AddHours(i).AddMinutes(30); m.Title = "Meeting " + i; From 840934502bb0f3b27e0c341a123d3f9782edc8fe Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 29 Jun 2021 17:35:22 -0600 Subject: [PATCH 04/14] Working on getting meeting change events to trigger properly --- .../UI/JoinConstants/UIBoolJoin.cs | 4 ++ .../Codec/iHasScheduleAwareness.cs | 45 ++++++++++++++----- .../VideoCodec/MockVC/MockVC.cs | 20 +++++++-- 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs index 23ab797e..293fddd5 100644 --- a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs +++ b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs @@ -764,6 +764,10 @@ namespace PepperDash.Essentials /// public const uint NextMeetingModalVisible = 15049; /// + /// 15050 + /// + public const uint NextMeetingNotificationRibbonVisible = 15050; + /// /// 15051 /// public const uint Display1SelectPressAndFb = 15051; diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs index 8799b33b..5e2b1c23 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs @@ -4,13 +4,15 @@ using System.Linq; using System.Text; using Crestron.SimplSharp; +using PepperDash.Core; + using Newtonsoft.Json; namespace PepperDash.Essentials.Devices.Common.Codec { public enum eMeetingEventChangeType { - Unkown = 0, + Unknown = 0, MeetingStartWarning, MeetingStart, MeetingEndWarning, @@ -34,6 +36,10 @@ namespace PepperDash.Essentials.Devices.Common.Codec private int _meetingWarningMinutes = 5; + private Meeting _previousChangedMeeting; + + private eMeetingEventChangeType _previousChangeType = eMeetingEventChangeType.Unknown; + public int MeetingWarningMinutes { get { return _meetingWarningMinutes; } @@ -90,24 +96,39 @@ namespace PepperDash.Essentials.Devices.Common.Codec { // Iterate the meeting list and check if any meeting need to do anythingk - const double meetingTimeEpsilon = 0.0001; + const double meetingTimeEpsilon = 0.05; foreach (var m in Meetings) { - var changeType = eMeetingEventChangeType.Unkown; + var changeType = eMeetingEventChangeType.Unknown; - if (m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes) // Meeting is about to start + //Debug.Console(2, "Math.Abs(m.TimeToMeetingEnd.TotalMinutes) = {0}", Math.Abs(m.TimeToMeetingEnd.TotalMinutes)); + if (_previousChangeType != eMeetingEventChangeType.MeetingStartWarning && m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingStart.Seconds > 0) // Meeting is about to start + { + Debug.Console(2, "MeetingStartWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingStart.TotalMinutes, m.TimeToMeetingStart.Seconds); changeType = eMeetingEventChangeType.MeetingStartWarning; - else if (Math.Abs(m.TimeToMeetingStart.TotalMinutes) < meetingTimeEpsilon) // Meeting Start + } + else if (_previousChangeType != eMeetingEventChangeType.MeetingStart && Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting Start + { + Debug.Console(2, "MeetingStart"); changeType = eMeetingEventChangeType.MeetingStart; - else if (m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes) // Meeting is about to end + } + else if (_previousChangeType != eMeetingEventChangeType.MeetingEndWarning && m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingEnd.Seconds > 0) // Meeting is about to end changeType = eMeetingEventChangeType.MeetingEndWarning; - else if (Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting has ended + else if (_previousChangeType != eMeetingEventChangeType.MeetingEnd && Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting has ended changeType = eMeetingEventChangeType.MeetingEnd; - if (changeType != eMeetingEventChangeType.Unkown) - OnMeetingChange(changeType, m); - } + if (changeType != eMeetingEventChangeType.Unknown) + { + // check to make sure this is not a redundant event for one that was fired last + if (_previousChangedMeeting == null || (_previousChangedMeeting != m && _previousChangeType != changeType)) + { + _previousChangeType = changeType; + _previousChangedMeeting = m; + OnMeetingChange(changeType, m); + } + } + } } } @@ -169,8 +190,10 @@ namespace PepperDash.Essentials.Devices.Common.Codec { get { - return StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now + var joinable = StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now && DateTime.Now <= EndTime; //.AddMinutes(-5); + Debug.Console(2, "Meeting Id: {0} joinable: {1}", Id, joinable); + return joinable; } } //public string ConferenceNumberToDial { get; set; } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs index a947a1d1..b87f1fa8 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs @@ -139,7 +139,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public override void Dial(Meeting meeting) { - throw new NotImplementedException(); + Debug.Console(1, this, "Dial Meeting: {0}", meeting.Id); + var call = new CodecActiveCallItem() { Name = meeting.Title, Number = meeting.Id, Id = meeting.Id, Status = eCodecCallStatus.Dialing, Direction = eCodecCallDirection.Outgoing, Type = eCodecCallType.Video }; + ActiveCalls.Add(call); + OnCallStatusChange(call); + + //ActiveCallCountFeedback.FireUpdate(); + // Simulate 2-second ring, then connecting, then connected + new CTimer(o => + { + call.Type = eCodecCallType.Video; + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call); + new CTimer(oo => SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connected, call), 1000); + }, 2000); + } /// @@ -396,14 +409,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (_CodecSchedule == null || _CodecSchedule.Meetings.Count == 0 || _CodecSchedule.Meetings[_CodecSchedule.Meetings.Count - 1].StartTime < DateTime.Now) { - _CodecSchedule = new CodecScheduleAwareness(10000); + _CodecSchedule = new CodecScheduleAwareness(1000); for (int i = 0; i < 5; i++) { var m = new Meeting(); + m.MinutesBeforeMeeting = 5; m.Id = i.ToString(); m.Organizer = "Employee " + 1; m.StartTime = DateTime.Now.AddMinutes(3).AddHours(i); - m.EndTime = DateTime.Now.AddHours(i).AddMinutes(30); + m.EndTime = DateTime.Now.AddHours(i).AddMinutes(55); m.Title = "Meeting " + i; m.Calls.Add(new Call() { Number = i + "meeting@fake.com"}); _CodecSchedule.Meetings.Add(m); From e964172200d777bd940d698145a343a6ef703e5f Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 2 Jul 2021 15:01:17 -0600 Subject: [PATCH 05/14] #729 Updates to get CheckSchedule method working as designed --- .../Display/MockDisplay.cs | 3 + .../Codec/iHasScheduleAwareness.cs | 76 +++++++++++++------ .../VideoCodec/MockVC/MockVC.cs | 4 +- 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs index dcdba6d8..eb529376 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs @@ -59,6 +59,9 @@ namespace PepperDash.Essentials.Core VolumeLevelFeedback = new IntFeedback(() => { return _FakeVolumeLevel; }); MuteFeedback = new BoolFeedback("MuteOn", () => _IsMuted); + + WarmupTime = 10000; + CooldownTime = 5000; } public override void PowerOn() diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs index 5e2b1c23..24f1968b 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs @@ -10,13 +10,14 @@ using Newtonsoft.Json; namespace PepperDash.Essentials.Devices.Common.Codec { + [Flags] public enum eMeetingEventChangeType { Unknown = 0, - MeetingStartWarning, - MeetingStart, - MeetingEndWarning, - MeetingEnd + MeetingStartWarning = 1, + MeetingStart = 2, + MeetingEndWarning = 4, + MeetingEnd = 8 } public interface IHasScheduleAwareness @@ -83,50 +84,69 @@ namespace PepperDash.Essentials.Devices.Common.Codec _scheduleChecker = new CTimer(CheckSchedule, null, pollTime, pollTime); } + /// + /// Helper method to fire MeetingEventChange. Should only fire once for each changeType on each meeting + /// + /// + /// private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting) { - var handler = MeetingEventChange; - if (handler != null) + Debug.Console(2, "*****************OnMeetingChange. id: {0} changeType: {1}**********************", meeting.Id, changeType); + if (changeType != (changeType & meeting.NotifiedChangeTypes)) { - handler(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting }); + // Add this change type to the NotifiedChangeTypes + meeting.NotifiedChangeTypes |= changeType; + + var handler = MeetingEventChange; + if (handler != null) + { + handler(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting }); + } + } + else + { + Debug.Console(2, "Meeting: {0} already notified of changeType: {1}", meeting.Id, changeType); } } + + /// + /// Checks the schedule to see if any MeetingEventChange updates should be fired + /// + /// private void CheckSchedule(object o) { - // Iterate the meeting list and check if any meeting need to do anythingk + // Iterate the meeting list and check if any meeting need to do anything const double meetingTimeEpsilon = 0.05; foreach (var m in Meetings) { var changeType = eMeetingEventChangeType.Unknown; - //Debug.Console(2, "Math.Abs(m.TimeToMeetingEnd.TotalMinutes) = {0}", Math.Abs(m.TimeToMeetingEnd.TotalMinutes)); - if (_previousChangeType != eMeetingEventChangeType.MeetingStartWarning && m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingStart.Seconds > 0) // Meeting is about to start + if (eMeetingEventChangeType.MeetingStartWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStartWarning) && m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingStart.Seconds > 0) // Meeting is about to start { - Debug.Console(2, "MeetingStartWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingStart.TotalMinutes, m.TimeToMeetingStart.Seconds); + Debug.Console(2, "********************* MeetingStartWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingStart.TotalMinutes, m.TimeToMeetingStart.Seconds); changeType = eMeetingEventChangeType.MeetingStartWarning; } - else if (_previousChangeType != eMeetingEventChangeType.MeetingStart && Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting Start + else if (eMeetingEventChangeType.MeetingStart != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStart) && Math.Abs(m.TimeToMeetingStart.TotalMinutes) < meetingTimeEpsilon) // Meeting Start { - Debug.Console(2, "MeetingStart"); + Debug.Console(2, "********************* MeetingStart"); changeType = eMeetingEventChangeType.MeetingStart; } - else if (_previousChangeType != eMeetingEventChangeType.MeetingEndWarning && m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingEnd.Seconds > 0) // Meeting is about to end + else if (eMeetingEventChangeType.MeetingEndWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEndWarning) && m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingEnd.Seconds > 0) // Meeting is about to end + { + Debug.Console(2, "********************* MeetingEndWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingEnd.TotalMinutes, m.TimeToMeetingEnd.Seconds); changeType = eMeetingEventChangeType.MeetingEndWarning; - else if (_previousChangeType != eMeetingEventChangeType.MeetingEnd && Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting has ended + } + else if (eMeetingEventChangeType.MeetingEnd != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEnd) && Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting has ended + { + Debug.Console(2, "********************* MeetingEnd"); changeType = eMeetingEventChangeType.MeetingEnd; + } if (changeType != eMeetingEventChangeType.Unknown) { - // check to make sure this is not a redundant event for one that was fired last - if (_previousChangedMeeting == null || (_previousChangedMeeting != m && _previousChangeType != changeType)) - { - _previousChangeType = changeType; - _previousChangedMeeting = m; - - OnMeetingChange(changeType, m); - } + OnMeetingChange(changeType, m); } } @@ -191,8 +211,8 @@ namespace PepperDash.Essentials.Devices.Common.Codec get { var joinable = StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now - && DateTime.Now <= EndTime; //.AddMinutes(-5); - Debug.Console(2, "Meeting Id: {0} joinable: {1}", Id, joinable); + && DateTime.Now <= EndTime.AddMinutes(-5); + //Debug.Console(2, "Meeting Id: {0} joinable: {1}", Id, joinable); return joinable; } } @@ -205,6 +225,12 @@ namespace PepperDash.Essentials.Devices.Common.Codec [JsonProperty("calls")] public List Calls { get; private set; } + /// + /// Tracks the change types that have already been notified for + /// + [JsonIgnore] + public eMeetingEventChangeType NotifiedChangeTypes { get; set; } + public Meeting() { Calls = new List(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs index b87f1fa8..ca199957 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs @@ -416,8 +416,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec m.MinutesBeforeMeeting = 5; m.Id = i.ToString(); m.Organizer = "Employee " + 1; - m.StartTime = DateTime.Now.AddMinutes(3).AddHours(i); - m.EndTime = DateTime.Now.AddHours(i).AddMinutes(55); + m.StartTime = DateTime.Now.AddMinutes(6).AddHours(i); + m.EndTime = DateTime.Now.AddHours(i).AddMinutes(16); m.Title = "Meeting " + i; m.Calls.Add(new Call() { Number = i + "meeting@fake.com"}); _CodecSchedule.Meetings.Add(m); From d95ee27979219fc1df0470ca28b415371549b493 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 2 Jul 2021 15:01:51 -0600 Subject: [PATCH 06/14] #728 corrects casing of folder name in Global.FilePathPrefix at startup --- PepperDashEssentials/ControlSystem.cs | 35 ++++++++++++++++++++------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index a8002f7e..e4c521b5 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -131,29 +131,46 @@ namespace PepperDash.Essentials if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server) // Handles 3-series running Windows CE OS { - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on {1} Appliance", Global.AssemblyVersion, Global.ProcessorSeries.ToString()); + string userFolder; + string nvramFolder; + bool is4series = false; + + if (eCrestronSeries.Series4 == (Global.ProcessorSeries & eCrestronSeries.Series4)) // Handle 4-series + { + is4series = true; + // Set path to user/ + userFolder = "user"; + nvramFolder = "nvram"; + } + else + { + userFolder = "User"; + nvramFolder = "Nvram"; + } + + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on {1} Appliance", Global.AssemblyVersion, is4series ? "4-series" : "3-series"); // Check if User/ProgramX exists - if (Directory.Exists(Global.ApplicationDirectoryPathPrefix + dirSeparator + "User" + if (Directory.Exists(Global.ApplicationDirectoryPathPrefix + dirSeparator + userFolder + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber))) { - Debug.Console(0, @"User/program{0} directory found", InitialParametersClass.ApplicationNumber); - filePathPrefix = directoryPrefix + dirSeparator + "User" + Debug.Console(0, @"{0}/program{1} directory found", userFolder, InitialParametersClass.ApplicationNumber); + filePathPrefix = directoryPrefix + dirSeparator + userFolder + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator; } // Check if Nvram/Programx exists - else if (Directory.Exists(directoryPrefix + dirSeparator + "Nvram" + else if (Directory.Exists(directoryPrefix + dirSeparator + nvramFolder + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber))) { - Debug.Console(0, @"Nvram/program{0} directory found", InitialParametersClass.ApplicationNumber); - filePathPrefix = directoryPrefix + dirSeparator + "Nvram" + Debug.Console(0, @"{0}/program{1} directory found", nvramFolder, InitialParametersClass.ApplicationNumber); + filePathPrefix = directoryPrefix + dirSeparator + nvramFolder + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator; } // If neither exists, set path to User/ProgramX else { - Debug.Console(0, @"No previous directory found. Using User/program{0}", InitialParametersClass.ApplicationNumber); - filePathPrefix = directoryPrefix + dirSeparator + "User" + Debug.Console(0, @"No previous directory found. Using {0}/program{1}", userFolder, InitialParametersClass.ApplicationNumber); + filePathPrefix = directoryPrefix + dirSeparator + userFolder + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator; } } From 2181410927cc69b0b9ca24b87eb4640539ec923d Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 12 Jul 2021 17:22:36 -0600 Subject: [PATCH 07/14] #736 Adds IEssentialsRoom and IEssentialsHuddleSpaceRoom interfaces Refactors all references to EssentialsRoomBase and EssentialsHuddleSpaceRoom to use the new interfaces instead --- PepperDashEssentials/ControlSystem.cs | 6 +- .../PepperDashEssentials.csproj | 1 + .../Room/Config/EssentialsRoomConfig.cs | 4 +- .../EsentialsRoomEmergencyContactClosure.cs | 4 +- .../Room/Types/EssentialsDualDisplayRoom.cs | 4 +- .../Room/Types/EssentialsHuddleSpaceRoom.cs | 2 +- .../Room/Types/EssentialsHuddleVtc1Room.cs | 6 +- .../Room/Types/IEssentialsHuddleSpaceRoom.cs | 28 +++ .../UI/EssentialsTouchpanelController.cs | 4 +- .../UIDrivers/DualDisplayRouting.cs | 6 +- .../Essentials/EssentialsHeaderDriver.cs | 6 +- ...tialsPresentationPanelAvFunctionsDriver.cs | 6 +- .../EssentialsHuddlePanelAvFunctionsDriver.cs | 14 +- .../UIDrivers/SmartObjectRoomsList.cs | 6 +- .../UIDrivers/SourceChangeArgs.cs | 2 +- .../DeviceTypeInterfaces/IMobileControl.cs | 2 +- .../Devices/EssentialsDevice.cs | 222 +++++++++--------- .../Devices/IProjectorInterfaces.cs | 8 +- .../Devices/IReconfigurableDevice.cs | 19 ++ .../Devices/ReconfigurableDevice.cs | 2 +- ...lsHuddleSpaceFusionSystemControllerBase.cs | 4 +- .../Fusion/FusionCustomPropertiesBridge.cs | 2 +- .../PepperDash_Essentials_Core.csproj | 2 + .../RoomOnToDefaultSourceWhenOccupied.cs | 4 +- .../Room/EssentialsRoomBase.cs | 2 +- .../Room/IEssentialsRoom.cs | 66 ++++++ .../Room/Interfaces.cs | 5 +- 27 files changed, 278 insertions(+), 159 deletions(-) create mode 100644 PepperDashEssentials/Room/Types/IEssentialsHuddleSpaceRoom.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IReconfigurableDevice.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/IEssentialsRoom.cs diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index e4c521b5..6d3ca5c6 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -452,7 +452,7 @@ namespace PepperDash.Essentials foreach (var roomConfig in ConfigReader.ConfigObject.Rooms) { - var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as EssentialsRoomBase; + var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as IEssentialsRoom; if (room != null) { // default IPID @@ -474,7 +474,7 @@ namespace PepperDash.Essentials } } - if (room is EssentialsHuddleSpaceRoom) + if (room is IEssentialsHuddleSpaceRoom) { DeviceManager.AddDevice(room); @@ -524,7 +524,7 @@ namespace PepperDash.Essentials } - private static void CreateMobileControlBridge(EssentialsRoomBase room) + private static void CreateMobileControlBridge(IEssentialsRoom room) { var mobileControl = GetMobileControlDevice(); diff --git a/PepperDashEssentials/PepperDashEssentials.csproj b/PepperDashEssentials/PepperDashEssentials.csproj index 7b548dd5..14bd450a 100644 --- a/PepperDashEssentials/PepperDashEssentials.csproj +++ b/PepperDashEssentials/PepperDashEssentials.csproj @@ -149,6 +149,7 @@ + diff --git a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs index 6a59cc56..5ec0565d 100644 --- a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs +++ b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs @@ -47,7 +47,7 @@ namespace PepperDash.Essentials.Room.Config /// Gets and operating, standalone emergegncy object that can be plugged into a room. /// Returns null if there is no emergency defined /// - public static EssentialsRoomEmergencyBase GetEmergency(EssentialsRoomPropertiesConfig props, EssentialsRoomBase room) + public static EssentialsRoomEmergencyBase GetEmergency(EssentialsRoomPropertiesConfig props, IEssentialsRoom room) { // This emergency var emergency = props.Emergency; @@ -96,7 +96,7 @@ namespace PepperDash.Essentials.Room.Config if (behaviour == "trackroomstate") { // Tie LED enable to room power state - var essRoom = room as EssentialsRoomBase; + var essRoom = room as IEssentialsRoom; essRoom.OnFeedback.OutputChange += (o, a) => { if (essRoom.OnFeedback.BoolValue) diff --git a/PepperDashEssentials/Room/Emergency/EsentialsRoomEmergencyContactClosure.cs b/PepperDashEssentials/Room/Emergency/EsentialsRoomEmergencyContactClosure.cs index ab40d2fe..c40ed496 100644 --- a/PepperDashEssentials/Room/Emergency/EsentialsRoomEmergencyContactClosure.cs +++ b/PepperDashEssentials/Room/Emergency/EsentialsRoomEmergencyContactClosure.cs @@ -17,11 +17,11 @@ namespace PepperDash.Essentials.Room public class EssentialsRoomEmergencyContactClosure : EssentialsRoomEmergencyBase { - EssentialsRoomBase Room; + IEssentialsRoom Room; string Behavior; bool TriggerOnClose; - public EssentialsRoomEmergencyContactClosure(string key, EssentialsRoomEmergencyConfig config, EssentialsRoomBase room) : + public EssentialsRoomEmergencyContactClosure(string key, EssentialsRoomEmergencyConfig config, IEssentialsRoom room) : base(key) { Room = room; diff --git a/PepperDashEssentials/Room/Types/EssentialsDualDisplayRoom.cs b/PepperDashEssentials/Room/Types/EssentialsDualDisplayRoom.cs index ccce0af5..d58f6ac7 100644 --- a/PepperDashEssentials/Room/Types/EssentialsDualDisplayRoom.cs +++ b/PepperDashEssentials/Room/Types/EssentialsDualDisplayRoom.cs @@ -645,9 +645,9 @@ namespace PepperDash.Essentials public static void AllRoomsOff() { var allRooms = DeviceManager.AllDevices.Where(d => - d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions); + d is IEssentialsHuddleSpaceRoom && !(d as IEssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions); foreach (var room in allRooms) - (room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff", (room as EssentialsHuddleSpaceRoom).SourceListKey); + (room as IEssentialsHuddleSpaceRoom).RunRouteAction("roomOff", (room as IEssentialsHuddleSpaceRoom).SourceListKey); } #region IPrivacy Members diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs index 9f388252..7a57e9c1 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs @@ -13,7 +13,7 @@ using PepperDash.Essentials.Room.Config; namespace PepperDash.Essentials { - public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasCurrentVolumeControls, IHasDefaultDisplay + public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IEssentialsHuddleSpaceRoom { public event EventHandler CurrentVolumeDeviceChange; public event SourceInfoChangeHandler CurrentSourceChange; diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index 85cfe90f..e6b12f4e 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -733,10 +733,10 @@ namespace PepperDash.Essentials /// public static void AllRoomsOff() { - var allRooms = DeviceManager.AllDevices.Where(d => - d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions); + var allRooms = DeviceManager.AllDevices.Where(d => + d is IEssentialsRoom && !(d as IEssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions); foreach (var room in allRooms) - (room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff"); + (room as IEssentialsHuddleSpaceRoom).RunRouteAction("roomOff"); } diff --git a/PepperDashEssentials/Room/Types/IEssentialsHuddleSpaceRoom.cs b/PepperDashEssentials/Room/Types/IEssentialsHuddleSpaceRoom.cs new file mode 100644 index 00000000..6feff235 --- /dev/null +++ b/PepperDashEssentials/Room/Types/IEssentialsHuddleSpaceRoom.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; +using PepperDash.Essentials.Room.Config; +using PepperDash.Essentials.Core.Devices; + +using PepperDash.Core; + +namespace PepperDash.Essentials +{ + public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay + { + bool ExcludeFromGlobalFunctions { get; } + + void RunRouteAction(string routeKey); + + EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; } + + IBasicVolumeControls CurrentVolumeControls { get; } + + event EventHandler CurrentVolumeDeviceChange; + } +} \ No newline at end of file diff --git a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs index 65039872..5c4349fd 100644 --- a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs +++ b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs @@ -222,7 +222,7 @@ namespace PepperDash.Essentials // spin up different room drivers depending on room type var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey); - if (room is EssentialsHuddleSpaceRoom) + if (room is IEssentialsHuddleSpaceRoom) { // Screen Saver Driver mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, props); @@ -236,7 +236,7 @@ namespace PepperDash.Essentials var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props); avDriver.DefaultRoomKey = props.DefaultRoomKey; mainDriver.AvDriver = avDriver; - avDriver.CurrentRoom = room as EssentialsHuddleSpaceRoom; + avDriver.CurrentRoom = room as IEssentialsHuddleSpaceRoom; // Environment Driver if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0) diff --git a/PepperDashEssentials/UIDrivers/DualDisplayRouting.cs b/PepperDashEssentials/UIDrivers/DualDisplayRouting.cs index 1aeb7a3c..4b29061d 100644 --- a/PepperDashEssentials/UIDrivers/DualDisplayRouting.cs +++ b/PepperDashEssentials/UIDrivers/DualDisplayRouting.cs @@ -146,18 +146,18 @@ // } -// void CurrentRoom_CurrentSourceInfoChange(EssentialsRoomBase room, SourceListItem info, ChangeType type) +// void CurrentRoom_CurrentSourceInfoChange(IEssentialsRoom room, SourceListItem info, ChangeType type) // { // } -// void CurrentRoom_CurrentDisplay1SourceChange(EssentialsRoomBase room, SourceListItem info, ChangeType type) +// void CurrentRoom_CurrentDisplay1SourceChange(IEssentialsRoom room, SourceListItem info, ChangeType type) // { // TriList.StringInput[UIStringJoin.Display1SourceLabel].StringValue = PendingSource.PreferredName; // } -// void CurrentRoom_CurrentDisplay2SourceChange(EssentialsRoomBase room, SourceListItem info, ChangeType type) +// void CurrentRoom_CurrentDisplay2SourceChange(IEssentialsRoom room, SourceListItem info, ChangeType type) // { // TriList.StringInput[UIStringJoin.Display2SourceLabel].StringValue = PendingSource.PreferredName; // } diff --git a/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs b/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs index ccaedd9c..df87c8f4 100644 --- a/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs +++ b/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs @@ -52,7 +52,7 @@ namespace PepperDash.Essentials CaretInterlock = new JoinedSigInterlock(TriList); } - void SetUpGear(IAVDriver avDriver, EssentialsRoomBase currentRoom) + void SetUpGear(IAVDriver avDriver, IEssentialsRoom currentRoom) { // Gear TriList.SetString(UIStringJoin.HeaderButtonIcon5, "Gear"); @@ -105,7 +105,7 @@ namespace PepperDash.Essentials { string message = null; var room = DeviceManager.GetDeviceForKey(Config.DefaultRoomKey) - as EssentialsHuddleSpaceRoom; + as IEssentialsHuddleSpaceRoom; if (room != null) message = room.PropertiesConfig.HelpMessage; else @@ -283,7 +283,7 @@ namespace PepperDash.Essentials /// /// Sets up Header Buttons for the EssentialsHuddleSpaceRoom type /// - public void SetupHeaderButtons(EssentialsHuddlePanelAvFunctionsDriver avDriver, EssentialsHuddleSpaceRoom currentRoom) + public void SetupHeaderButtons(EssentialsHuddlePanelAvFunctionsDriver avDriver, IEssentialsHuddleSpaceRoom currentRoom) { HeaderButtonsAreSetUp = false; diff --git a/PepperDashEssentials/UIDrivers/Essentials/EssentialsPresentationPanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/Essentials/EssentialsPresentationPanelAvFunctionsDriver.cs index 4a8cb53c..9c8514ea 100644 --- a/PepperDashEssentials/UIDrivers/Essentials/EssentialsPresentationPanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/Essentials/EssentialsPresentationPanelAvFunctionsDriver.cs @@ -983,7 +983,7 @@ // /// // /// Handles source change // /// -// void _CurrentRoom_SourceInfoChange(EssentialsRoomBase room, +// void _CurrentRoom_SourceInfoChange(IEssentialsRoom room, // SourceListItem info, ChangeType change) // { // if (change == ChangeType.WillChange) @@ -995,7 +995,7 @@ // /// // /// // /// -// void _CurrentRoom_CurrentDisplay1SourceChange(EssentialsRoomBase room, SourceListItem info, ChangeType type) +// void _CurrentRoom_CurrentDisplay1SourceChange(IEssentialsRoom room, SourceListItem info, ChangeType type) // { // if (type == ChangeType.DidChange) // { @@ -1021,7 +1021,7 @@ // /// // /// // /// -// void _CurrentRoom_CurrentDisplay2SourceChange(EssentialsRoomBase room, SourceListItem info, ChangeType type) +// void _CurrentRoom_CurrentDisplay2SourceChange(IEssentialsRoom room, SourceListItem info, ChangeType type) // { // if (type == ChangeType.DidChange) // { diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs index f22565e5..a0d5947c 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs @@ -78,7 +78,7 @@ namespace PepperDash.Essentials /// /// /// - public EssentialsHuddleSpaceRoom CurrentRoom + public IEssentialsHuddleSpaceRoom CurrentRoom { get { return _CurrentRoom; } set @@ -86,7 +86,7 @@ namespace PepperDash.Essentials SetCurrentRoom(value); } } - EssentialsHuddleSpaceRoom _CurrentRoom; + IEssentialsHuddleSpaceRoom _CurrentRoom; /// /// @@ -498,7 +498,7 @@ namespace PepperDash.Essentials TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = true; // Run default source when room is off and share is pressed if (!CurrentRoom.OnFeedback.BoolValue) - CurrentRoom.RunDefaultPresentRoute(); + (CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute(); } @@ -583,7 +583,7 @@ namespace PepperDash.Essentials void UiSelectSource(string key) { // Run the route and when it calls back, show the source - CurrentRoom.RunRouteAction(key, new Action(() => { })); + CurrentRoom.RunRouteAction(key); } /// @@ -745,7 +745,7 @@ namespace PepperDash.Essentials /// /// Helper for property setter. Sets the panel to the given room, latching up all functionality /// - public void RefreshCurrentRoom(EssentialsHuddleSpaceRoom room) + public void RefreshCurrentRoom(IEssentialsHuddleSpaceRoom room) { if (_CurrentRoom != null) { @@ -836,7 +836,7 @@ namespace PepperDash.Essentials } } - void SetCurrentRoom(EssentialsHuddleSpaceRoom room) + void SetCurrentRoom(IEssentialsHuddleSpaceRoom room) { if (_CurrentRoom == room) return; // Disconnect current (probably never called) @@ -871,7 +871,7 @@ namespace PepperDash.Essentials UpdateMCJoins(_CurrentRoom); } - void UpdateMCJoins(EssentialsHuddleSpaceRoom room) + void UpdateMCJoins(IEssentialsHuddleSpaceRoom room) { TriList.SetString(UIStringJoin.RoomMcUrl, room.MobileControlRoomBridge.McServerUrl); TriList.SetString(UIStringJoin.RoomMcQrCodeUrl, room.MobileControlRoomBridge.QrCodeUrl); diff --git a/PepperDashEssentials/UIDrivers/SmartObjectRoomsList.cs b/PepperDashEssentials/UIDrivers/SmartObjectRoomsList.cs index e43abc09..2543e664 100644 --- a/PepperDashEssentials/UIDrivers/SmartObjectRoomsList.cs +++ b/PepperDashEssentials/UIDrivers/SmartObjectRoomsList.cs @@ -38,7 +38,7 @@ namespace PepperDash.Essentials /// /// Sets feedback for the given room /// - public void SetFeedbackForRoom(EssentialsHuddleSpaceRoom room) + public void SetFeedbackForRoom(IEssentialsHuddleSpaceRoom room) { var itemToSet = Items.FirstOrDefault(i => i.Room == room); if (itemToSet != null) @@ -48,11 +48,11 @@ namespace PepperDash.Essentials public class SmartObjectRoomsListItem { - public EssentialsHuddleSpaceRoom Room { get; private set; } + public IEssentialsHuddleSpaceRoom Room { get; private set; } SmartObjectRoomsList Parent; public uint Index { get; private set; } - public SmartObjectRoomsListItem(EssentialsHuddleSpaceRoom room, uint index, SmartObjectRoomsList parent, + public SmartObjectRoomsListItem(IEssentialsHuddleSpaceRoom room, uint index, SmartObjectRoomsList parent, Action buttonAction) { Room = room; diff --git a/PepperDashEssentials/UIDrivers/SourceChangeArgs.cs b/PepperDashEssentials/UIDrivers/SourceChangeArgs.cs index c777c08e..5c034084 100644 --- a/PepperDashEssentials/UIDrivers/SourceChangeArgs.cs +++ b/PepperDashEssentials/UIDrivers/SourceChangeArgs.cs @@ -12,5 +12,5 @@ namespace PepperDash.Essentials ///// ///// The handler type for a Room's SourceInfoChange ///// - //public delegate void SourceInfoChangeHandler(EssentialsRoomBase room, SourceListItem info, ChangeType type); + //public delegate void SourceInfoChangeHandler(IEssentialsRoom room, SourceListItem info, ChangeType type); } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs index c87e7865..a2dda43a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs @@ -8,7 +8,7 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces /// public interface IMobileControl : IKeyed { - void CreateMobileControlRoomBridge(EssentialsRoomBase room, IMobileControl parent); + void CreateMobileControlRoomBridge(IEssentialsRoom room, IMobileControl parent); void LinkSystemMonitorToAppServer(); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs index 8d7f2c8d..781101d4 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs @@ -1,113 +1,113 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharp.Reflection; - -using PepperDash.Core; -using PepperDash.Essentials.Core.Config; - -namespace PepperDash.Essentials.Core -{ - /// - /// Defines the basic needs for an EssentialsDevice to enable it to be build by an IDeviceFactory class - /// - [Description("The base Essentials Device Class")] - public abstract class EssentialsDevice : Device - { - protected EssentialsDevice(string key) - : base(key) - { - - } - - protected EssentialsDevice(string key, string name) - : base(key, name) - { - - } - } - - [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)] - public class DescriptionAttribute : Attribute - { - private string _Description; - - public DescriptionAttribute(string description) - { - Debug.Console(2, "Setting Description: {0}", description); - _Description = description; - } - - public string Description - { - get { return _Description; } - } - } - - [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)] - public class ConfigSnippetAttribute : Attribute - { - private string _ConfigSnippet; - - public ConfigSnippetAttribute(string configSnippet) - { - Debug.Console(2, "Setting Config Snippet {0}", configSnippet); - _ConfigSnippet = configSnippet; - } - - public string ConfigSnippet - { - get { return _ConfigSnippet; } - } - } - - /// - /// Devices the basic needs for a Device Factory - /// - public abstract class EssentialsDeviceFactory : IDeviceFactory where T:EssentialsDevice - { - #region IDeviceFactory Members - - /// - /// A list of strings that can be used in the type property of a DeviceConfig object to build an instance of this device - /// - public List TypeNames { get; protected set; } - - /// - /// Loads an item to the DeviceFactory.FactoryMethods dictionary for each entry in the TypeNames list - /// - public void LoadTypeFactories() - { - foreach (var typeName in TypeNames) - { - Debug.Console(2, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); - var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[]; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharp.Reflection; + +using PepperDash.Core; +using PepperDash.Essentials.Core.Config; + +namespace PepperDash.Essentials.Core +{ + /// + /// Defines the basic needs for an EssentialsDevice to enable it to be build by an IDeviceFactory class + /// + [Description("The base Essentials Device Class")] + public abstract class EssentialsDevice : Device + { + protected EssentialsDevice(string key) + : base(key) + { + + } + + protected EssentialsDevice(string key, string name) + : base(key, name) + { + + } + } + + [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)] + public class DescriptionAttribute : Attribute + { + private string _Description; + + public DescriptionAttribute(string description) + { + Debug.Console(2, "Setting Description: {0}", description); + _Description = description; + } + + public string Description + { + get { return _Description; } + } + } + + [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)] + public class ConfigSnippetAttribute : Attribute + { + private string _ConfigSnippet; + + public ConfigSnippetAttribute(string configSnippet) + { + Debug.Console(2, "Setting Config Snippet {0}", configSnippet); + _ConfigSnippet = configSnippet; + } + + public string ConfigSnippet + { + get { return _ConfigSnippet; } + } + } + + /// + /// Devices the basic needs for a Device Factory + /// + public abstract class EssentialsDeviceFactory : IDeviceFactory where T:EssentialsDevice + { + #region IDeviceFactory Members + + /// + /// A list of strings that can be used in the type property of a DeviceConfig object to build an instance of this device + /// + public List TypeNames { get; protected set; } + + /// + /// Loads an item to the DeviceFactory.FactoryMethods dictionary for each entry in the TypeNames list + /// + public void LoadTypeFactories() + { + foreach (var typeName in TypeNames) + { + Debug.Console(2, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); + var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[]; string description = descriptionAttribute[0].Description; - var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[]; - DeviceFactory.AddFactoryForType(typeName.ToLower(), description, typeof(T), BuildDevice); - } - } - - /// - /// The method that will build the device - /// - /// The device config - /// An instance of the device - public abstract EssentialsDevice BuildDevice(DeviceConfig dc); - - #endregion - } - - /// - /// Devices the basic needs for a Device Factory - /// - public abstract class EssentialsPluginDeviceFactory : EssentialsDeviceFactory, IPluginDeviceFactory where T : EssentialsDevice - { - /// - /// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33") - /// - public string MinimumEssentialsFrameworkVersion { get; protected set; } - } + var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[]; + DeviceFactory.AddFactoryForType(typeName.ToLower(), description, typeof(T), BuildDevice); + } + } + + /// + /// The method that will build the device + /// + /// The device config + /// An instance of the device + public abstract EssentialsDevice BuildDevice(DeviceConfig dc); + + #endregion + } + + /// + /// Devices the basic needs for a Device Factory + /// + public abstract class EssentialsPluginDeviceFactory : EssentialsDeviceFactory, IPluginDeviceFactory where T : EssentialsDevice + { + /// + /// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33") + /// + public string MinimumEssentialsFrameworkVersion { get; protected set; } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IProjectorInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IProjectorInterfaces.cs index 6efb7776..70e2e215 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IProjectorInterfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IProjectorInterfaces.cs @@ -1,7 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; using Crestron.SimplSharp; namespace PepperDash.Essentials.Core diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IReconfigurableDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IReconfigurableDevice.cs new file mode 100644 index 00000000..ab0e37c3 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IReconfigurableDevice.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using PepperDash.Essentials.Core.Config; + + +namespace PepperDash.Essentials.Core.Devices +{ + public interface IReconfigurableDevice + { + event EventHandler ConfigChanged; + + DeviceConfig Config { get; } + + void SetConfig(DeviceConfig config); + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs index 81988199..3239e192 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs @@ -15,7 +15,7 @@ namespace PepperDash.Essentials.Core.Devices /// /// /// - public abstract class ReconfigurableDevice : EssentialsDevice + public abstract class ReconfigurableDevice : EssentialsDevice, IReconfigurableDevice { public event EventHandler ConfigChanged; diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs index b26b1980..a172ab49 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs @@ -33,7 +33,7 @@ namespace PepperDash.Essentials.Core.Fusion protected FusionRoom FusionRoom; protected Dictionary FusionStaticAssets; public long PushNotificationTimeout = 5000; - protected EssentialsRoomBase Room; + protected IEssentialsRoom Room; public long SchedulePollInterval = 300000; private Event _currentMeeting; @@ -86,7 +86,7 @@ namespace PepperDash.Essentials.Core.Fusion #endregion - public EssentialsHuddleSpaceFusionSystemControllerBase(EssentialsRoomBase room, uint ipId, string joinMapKey) + public EssentialsHuddleSpaceFusionSystemControllerBase(IEssentialsRoom room, uint ipId, string joinMapKey) : base(room.Key + "-fusion") { try diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/FusionCustomPropertiesBridge.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/FusionCustomPropertiesBridge.cs index 01b230f9..89b9fcdb 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/FusionCustomPropertiesBridge.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/FusionCustomPropertiesBridge.cs @@ -82,7 +82,7 @@ namespace PepperDash.Essentials.Core.Fusion deviceConfig.Properties = JToken.FromObject(devProps); } - else if (device is EssentialsRoomBase) + else if (device is IEssentialsRoom) { // Set the room name if (!string.IsNullOrEmpty(roomInfo.Name)) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index e65b081b..6e48fd66 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -197,6 +197,7 @@ + @@ -288,6 +289,7 @@ + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs index f24daf82..81cbff9e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs @@ -38,7 +38,7 @@ namespace PepperDash.Essentials.Core ScheduledEventGroup FeatureEventGroup; - public EssentialsRoomBase Room { get; private set; } + public IEssentialsRoom Room { get; private set; } private Fusion.EssentialsHuddleSpaceFusionSystemControllerBase FusionRoom; @@ -84,7 +84,7 @@ namespace PepperDash.Essentials.Core /// void SetUpDevice() { - Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as EssentialsRoomBase; + Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as IEssentialsRoom; if (Room != null) { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs index cae027f5..0d8e9803 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs @@ -16,7 +16,7 @@ namespace PepperDash.Essentials.Core /// /// /// - public abstract class EssentialsRoomBase : ReconfigurableDevice + public abstract class EssentialsRoomBase : ReconfigurableDevice, IEssentialsRoom { /// /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/IEssentialsRoom.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/IEssentialsRoom.cs new file mode 100644 index 00000000..e83c4b2f --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/IEssentialsRoom.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +using PepperDash.Essentials.Core.DeviceTypeInterfaces; +using PepperDash.Essentials.Room.Config; +using PepperDash.Essentials.Core.Devices; + +using PepperDash.Core; + +namespace PepperDash.Essentials.Core +{ + /// + /// Describes the basic functionality of an EssentialsRoom + /// + public interface IEssentialsRoom : IKeyName, IReconfigurableDevice + { + BoolFeedback OnFeedback { get; } + + event EventHandler RoomOccupancyIsSet; + + BoolFeedback IsWarmingUpFeedback { get; } + BoolFeedback IsCoolingDownFeedback { get; } + + IOccupancyStatusProvider RoomOccupancy { get; } + bool OccupancyStatusProviderIsRemote { get; } + + bool IsMobileControlEnabled { get; } + IMobileControlRoomBridge MobileControlRoomBridge { get; } + + string SourceListKey { get; } + + SecondsCountdownTimer ShutdownPromptTimer { get; } + int ShutdownPromptSeconds { get; } + int ShutdownVacancySeconds { get; } + eShutdownType ShutdownType { get; } + + EssentialsRoomEmergencyBase Emergency { get; } + + Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; } + + string LogoUrlLightBkgnd { get; } + string LogoUrlDarkBkgnd { get; } + + eVacancyMode VacancyMode { get; } + + bool ZeroVolumeWhenSwtichingVolumeDevices { get; } + + void StartShutdown(eShutdownType type); + void StartRoomVacancyTimer(eVacancyMode mode); + + void Shutdown(); + + void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes); + + void PowerOnToDefaultOrLastSource(); + bool RunDefaultPresentRoute(); + + void SetDefaultLevels(); + + void RoomVacatedForTimeoutPeriod(object o); + } + +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Interfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Interfaces.cs index 82871228..592b0bd9 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Interfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Interfaces.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using Crestron.SimplSharp; + namespace PepperDash.Essentials.Core { /// @@ -64,5 +65,7 @@ namespace PepperDash.Essentials.Core { bool RunDefaultCallRoute(); } - + + + } \ No newline at end of file From a37814ab3c01c3370ab57a148bc90083491a7292 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 12 Jul 2021 21:49:54 -0600 Subject: [PATCH 08/14] #736 adds IEssentialsHuddleVtc1Room and refactors to use interface rather than EssentialsHudleVtc1Room --- PepperDashEssentials/ControlSystem.cs | 4 ++-- .../EssentialsHuddleVtc1FusionController.cs | 22 +++++++++---------- .../Room/Types/EssentialsHuddleVtc1Room.cs | 3 +-- .../Room/Types/IEssentialsHuddleSpaceRoom.cs | 20 +++++++++++++++++ .../UI/EssentialsTouchpanelController.cs | 6 ++--- .../Essentials/EssentialsHeaderDriver.cs | 2 +- ...entialsHuddleVtc1PanelAvFunctionsDriver.cs | 16 +++++++------- 7 files changed, 46 insertions(+), 27 deletions(-) diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index 6d3ca5c6..033d82fe 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -486,12 +486,12 @@ namespace PepperDash.Essentials CreateMobileControlBridge(room); } - else if (room is EssentialsHuddleVtc1Room) + else if (room is IEssentialsHuddleVtc1Room) { DeviceManager.AddDevice(room); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion"); - DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey)); + DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey)); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); diff --git a/PepperDashEssentials/Fusion/EssentialsHuddleVtc1FusionController.cs b/PepperDashEssentials/Fusion/EssentialsHuddleVtc1FusionController.cs index c4a68d4e..54d936f0 100644 --- a/PepperDashEssentials/Fusion/EssentialsHuddleVtc1FusionController.cs +++ b/PepperDashEssentials/Fusion/EssentialsHuddleVtc1FusionController.cs @@ -16,7 +16,7 @@ namespace PepperDash.Essentials.Fusion { BooleanSigData CodecIsInCall; - public EssentialsHuddleVtc1FusionController(EssentialsHuddleVtc1Room room, uint ipId, string joinMapKey) + public EssentialsHuddleVtc1FusionController(IEssentialsHuddleVtc1Room room, uint ipId, string joinMapKey) : base(room, ipId, joinMapKey) { @@ -37,7 +37,7 @@ namespace PepperDash.Essentials.Fusion { try { - var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec; + var codec = (Room as IEssentialsHuddleVtc1Room).VideoCodec; if (codec == null) { @@ -141,7 +141,7 @@ namespace PepperDash.Essentials.Fusion void codec_CallStatusChange(object sender, PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs e) { - var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec; + var codec = (Room as IEssentialsHuddleVtc1Room).VideoCodec; CodecIsInCall.InputSig.BoolValue = codec.IsInCall; } @@ -174,11 +174,11 @@ namespace PepperDash.Essentials.Fusion // Moved to CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(JoinMap.Display1CurrentSourceName.JoinNumber, JoinMap.Display1CurrentSourceName.AttributeName, eSigIoMask.InputSigOnly); // Don't think we need to get current status of this as nothing should be alive yet. - (Room as EssentialsHuddleVtc1Room).CurrentSourceChange += Room_CurrentSourceInfoChange; + (Room as IEssentialsHuddleVtc1Room).CurrentSourceChange += Room_CurrentSourceInfoChange; - FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as EssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource); - FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey)); + FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as IEssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource); + FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as IEssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey)); CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler; @@ -187,7 +187,7 @@ namespace PepperDash.Essentials.Fusion protected override void SetUpSources() { // Sources - var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as EssentialsHuddleVtc1Room).SourceListKey); + var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as IEssentialsHuddleVtc1Room).SourceListKey); if (dict != null) { // NEW PROCESS: @@ -238,7 +238,7 @@ namespace PepperDash.Essentials.Fusion else { Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'", - (Room as EssentialsHuddleVtc1Room).SourceListKey, Room.Key); + (Room as IEssentialsHuddleVtc1Room).SourceListKey, Room.Key); } } @@ -259,7 +259,7 @@ namespace PepperDash.Essentials.Fusion display.UsageTracker.DeviceUsageEnded += new EventHandler(UsageTracker_DeviceUsageEnded); } - var defaultDisplay = (Room as EssentialsHuddleVtc1Room).DefaultDisplay as DisplayBase; + var defaultDisplay = (Room as IEssentialsHuddleVtc1Room).DefaultDisplay as DisplayBase; if (defaultDisplay == null) { Debug.Console(1, this, "Cannot link null display to Fusion because default display is null"); @@ -332,7 +332,7 @@ namespace PepperDash.Essentials.Fusion string displayName = string.Format("Display {0} - ", displayIndex); - if (display == (Room as EssentialsHuddleVtc1Room).DefaultDisplay) + if (display == (Room as IEssentialsHuddleVtc1Room).DefaultDisplay) { // Power on var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig); @@ -351,7 +351,7 @@ namespace PepperDash.Essentials.Fusion // Current Source var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig); - defaultDisplaySourceNone.OutputSig.UserObject = new Action(b => { if (!b) (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey); }); ; + defaultDisplaySourceNone.OutputSig.UserObject = new Action(b => { if (!b) (Room as IEssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey); }); ; } } } diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index e6b12f4e..5e7b5c37 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -17,8 +17,7 @@ using PepperDash.Essentials.Core.DeviceTypeInterfaces; namespace PepperDash.Essentials { - public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IHasCurrentSourceInfoChange, - IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback + public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IEssentialsHuddleVtc1Room { private bool _codecExternalSourceChange; public event EventHandler CurrentVolumeDeviceChange; diff --git a/PepperDashEssentials/Room/Types/IEssentialsHuddleSpaceRoom.cs b/PepperDashEssentials/Room/Types/IEssentialsHuddleSpaceRoom.cs index 6feff235..efc126f6 100644 --- a/PepperDashEssentials/Room/Types/IEssentialsHuddleSpaceRoom.cs +++ b/PepperDashEssentials/Room/Types/IEssentialsHuddleSpaceRoom.cs @@ -8,6 +8,10 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.DeviceTypeInterfaces; using PepperDash.Essentials.Room.Config; using PepperDash.Essentials.Core.Devices; +using PepperDash.Essentials.Devices.Common.Codec; +using PepperDash.Essentials.Devices.Common.VideoCodec; +using PepperDash.Essentials.Devices.Common.AudioCodec; + using PepperDash.Core; @@ -25,4 +29,20 @@ namespace PepperDash.Essentials event EventHandler CurrentVolumeDeviceChange; } + + public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange, + IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback + { + EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; } + + void RunRouteAction(string routeKey); + + IHasScheduleAwareness ScheduleSource { get; } + + BoolFeedback InCallFeedback { get; } + + BoolFeedback PrivacyModeIsOnFeedback { get; } + + string DefaultCodecRouteString { get; } + } } \ No newline at end of file diff --git a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs index 5c4349fd..7873bf42 100644 --- a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs +++ b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs @@ -270,7 +270,7 @@ namespace PepperDash.Essentials tsw.Down.UserObject = new Action(avDriver.VolumeDownPress); } } - else if (room is EssentialsHuddleVtc1Room) + else if (room is IEssentialsHuddleVtc1Room) { Debug.Console(0, panelController, "Adding huddle space VTC AV driver"); @@ -284,11 +284,11 @@ namespace PepperDash.Essentials var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, props); var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(panelController.Panel, avDriver, - (room as EssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver); + (room as IEssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver); avDriver.SetVideoCodecDriver(codecDriver); avDriver.DefaultRoomKey = props.DefaultRoomKey; mainDriver.AvDriver = avDriver; - avDriver.CurrentRoom = room as EssentialsHuddleVtc1Room; + avDriver.CurrentRoom = room as IEssentialsHuddleVtc1Room; // Environment Driver if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0) diff --git a/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs b/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs index df87c8f4..fa6f67d5 100644 --- a/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs +++ b/PepperDashEssentials/UIDrivers/Essentials/EssentialsHeaderDriver.cs @@ -221,7 +221,7 @@ namespace PepperDash.Essentials /// /// Sets up Header Buttons for the EssentialsHuddleVtc1Room type /// - public void SetupHeaderButtons(EssentialsHuddleVtc1PanelAvFunctionsDriver avDriver, EssentialsHuddleVtc1Room currentRoom) + public void SetupHeaderButtons(EssentialsHuddleVtc1PanelAvFunctionsDriver avDriver, IEssentialsHuddleVtc1Room currentRoom) { HeaderButtonsAreSetUp = false; diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index a4e88e7e..6280f54e 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -50,7 +50,7 @@ namespace PepperDash.Essentials /// /// /// - public EssentialsHuddleVtc1Room CurrentRoom + public IEssentialsHuddleVtc1Room CurrentRoom { get { return _CurrentRoom; } set @@ -58,7 +58,7 @@ namespace PepperDash.Essentials SetCurrentRoom(value); } } - EssentialsHuddleVtc1Room _CurrentRoom; + IEssentialsHuddleVtc1Room _CurrentRoom; /// /// For hitting feedbacks @@ -652,7 +652,7 @@ namespace PepperDash.Essentials if (!CurrentRoom.OnFeedback.BoolValue) { // If there's no default, show UI elements - if (!CurrentRoom.RunDefaultPresentRoute()) + if (!(CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute()) TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); } } @@ -743,7 +743,7 @@ namespace PepperDash.Essentials void UiSelectSource(string key) { // Run the route and when it calls back, show the source - CurrentRoom.RunRouteAction(key, new Action(() => { })); + CurrentRoom.RunRouteAction(key); } /// @@ -894,7 +894,7 @@ namespace PepperDash.Essentials /// /// Helper for property setter. Sets the panel to the given room, latching up all functionality /// - void RefreshCurrentRoom(EssentialsHuddleVtc1Room room) + void RefreshCurrentRoom(IEssentialsHuddleVtc1Room room) { if (_CurrentRoom != null) @@ -969,7 +969,7 @@ namespace PepperDash.Essentials } } - void SetCurrentRoom(EssentialsHuddleVtc1Room room) + void SetCurrentRoom(IEssentialsHuddleVtc1Room room) { if (_CurrentRoom == room) return; // Disconnect current (probably never called) @@ -1004,7 +1004,7 @@ namespace PepperDash.Essentials UpdateMCJoins(_CurrentRoom); } - void UpdateMCJoins(EssentialsHuddleVtc1Room room) + void UpdateMCJoins(IEssentialsHuddleVtc1Room room) { TriList.SetString(UIStringJoin.RoomMcUrl, room.MobileControlRoomBridge.McServerUrl); TriList.SetString(UIStringJoin.RoomMcQrCodeUrl, room.MobileControlRoomBridge.QrCodeUrl); @@ -1443,7 +1443,7 @@ namespace PepperDash.Essentials /// public interface IAVWithVCDriver : IAVDriver { - EssentialsHuddleVtc1Room CurrentRoom { get; } + IEssentialsHuddleVtc1Room CurrentRoom { get; } PepperDash.Essentials.Core.Touchpanels.Keyboards.HabaneroKeyboardController Keyboard { get; } /// From 990090e1dec396f22fc10bc23f5d30d26f1d4c2a Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 19 Jul 2021 10:29:30 -0600 Subject: [PATCH 09/14] feat: Add support for C2N-IO --- .../Crestron IO/C2nIo/C2nIoController.cs | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/C2nIo/C2nIoController.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/C2nIo/C2nIoController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/C2nIo/C2nIoController.cs new file mode 100644 index 00000000..0b70288f --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/C2nIo/C2nIoController.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.GeneralIO; +using PepperDash.Core; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Config; + +namespace PepperDash.Essentials.Core.CrestronIO +{ + public class C2NIoController:CrestronGenericBaseDevice, IComPorts, IIROutputPorts, IRelayPorts + { + private C2nIo _device; + + public C2NIoController(string key, Func preActivationFunc, DeviceConfig config):base(key, config.Name) + { + AddPreActivationAction(() => + { + _device = preActivationFunc(config); + + RegisterCrestronGenericBase(_device); + }); + } + + #region Implementation of IComPorts + + public CrestronCollection ComPorts + { + get { return _device.ComPorts; } + } + + public int NumberOfComPorts + { + get { return _device.NumberOfComPorts; } + } + + #endregion + + #region Implementation of IIROutputPorts + + public CrestronCollection IROutputPorts + { + get { return _device.IROutputPorts; } + } + + public int NumberOfIROutputPorts + { + get { return _device.NumberOfIROutputPorts; } + } + + #endregion + + #region Implementation of IRelayPorts + + public CrestronCollection RelayPorts + { + get { return _device.RelayPorts; } + } + + public int NumberOfRelayPorts + { + get { return _device.NumberOfRelayPorts; } + } + + #endregion + } + + public class C2NIoControllerFactory : EssentialsDeviceFactory + { + public C2NIoControllerFactory() + { + TypeNames = new List() { "c2nio" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new C2N-IO Device"); + + return new C2NIoController(dc.Key, GetC2NIoDevice, dc); + } + + static C2nIo GetC2NIoDevice(DeviceConfig dc) + { + var control = CommFactory.GetControlPropertiesConfig(dc); + var cresnetId = control.CresnetIdInt; + var branchId = control.ControlPortNumber; + var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey; + + if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase)) + { + Debug.Console(0, "Device {0} is a valid cresnet master - creating new C2nIo", parentKey); + return new C2nIo(cresnetId, Global.ControlSystem); + } + var cresnetBridge = DeviceManager.GetDeviceForKey(parentKey) as IHasCresnetBranches; + + if (cresnetBridge != null) + { + Debug.Console(0, "Device {0} is a valid cresnet master - creating new C2nIo", parentKey); + return new C2nIo(cresnetId, cresnetBridge.CresnetBranches[branchId]); + } + Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey); + return null; + } + } +} \ No newline at end of file From 6946946c12e3b23710b85996fd267b54c7171481 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 19 Jul 2021 13:47:17 -0600 Subject: [PATCH 10/14] chore: Add c2nIoController to csproj --- .../PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 6e48fd66..3919d331 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -162,6 +162,7 @@ + From 760ec8be924285a39398fef908bd8b681b7495bb Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 19 Jul 2021 14:08:23 -0600 Subject: [PATCH 11/14] feat: Add occupancy aggregator factory and config --- .../IOccupancyStatusProviderAggregator.cs | 44 ++++++++++++++++--- .../Occupancy/OccupancyAggregatorConfig.cs | 15 +++++++ .../PepperDash_Essentials_Core.csproj | 1 + 3 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/OccupancyAggregatorConfig.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/IOccupancyStatusProviderAggregator.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/IOccupancyStatusProviderAggregator.cs index c321dcad..601edf67 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/IOccupancyStatusProviderAggregator.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/IOccupancyStatusProviderAggregator.cs @@ -2,17 +2,18 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using Crestron.SimplSharp; - +using Crestron.SimplSharp; +using Crestron.SimplSharpPro.GeneralIO; using PepperDash.Core; using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; namespace PepperDash.Essentials.Core { /// /// Aggregates the RoomIsOccupied feedbacks of one or more IOccupancyStatusProvider objects /// - public class IOccupancyStatusProviderAggregator : Device, IOccupancyStatusProvider + public class IOccupancyStatusProviderAggregator : EssentialsDevice, IOccupancyStatusProvider { /// /// Aggregated feedback of all linked IOccupancyStatusProvider devices @@ -21,16 +22,22 @@ namespace PepperDash.Essentials.Core { get { - return AggregatedOccupancyStatus.Output; + return _aggregatedOccupancyStatus.Output; } } - private BoolFeedbackOr AggregatedOccupancyStatus; + private readonly BoolFeedbackOr _aggregatedOccupancyStatus; public IOccupancyStatusProviderAggregator(string key, string name) : base(key, name) { - AggregatedOccupancyStatus = new BoolFeedbackOr(); + _aggregatedOccupancyStatus = new BoolFeedbackOr(); + } + + public IOccupancyStatusProviderAggregator(string key, string name, OccupancyAggregatorConfig config) + : this(dc.Key, dc.Name) + { + } /// @@ -39,7 +46,30 @@ namespace PepperDash.Essentials.Core /// public void AddOccupancyStatusProvider(IOccupancyStatusProvider statusProvider) { - AggregatedOccupancyStatus.AddOutputIn(statusProvider.RoomIsOccupiedFeedback); + _aggregatedOccupancyStatus.AddOutputIn(statusProvider.RoomIsOccupiedFeedback); + } + + public void RemoveOccupancyStatusProvider(IOccupancyStatusProvider statusProvider) + { + _aggregatedOccupancyStatus.RemoveOutputIn(statusProvider.RoomIsOccupiedFeedback); } + } + + public class OccupancyAggregatorFactory : EssentialsDeviceFactory + { + public OccupancyAggregatorFactory() + { + TypeNames = new List { "glsodtccn" }; + } + + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new GlsOccupancySensorBaseController Device"); + + var config = dc.Properties.ToObject(); + + return new IOccupancyStatusProviderAggregator(dc.Key, dc.Name, config); + } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/OccupancyAggregatorConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/OccupancyAggregatorConfig.cs new file mode 100644 index 00000000..7909de04 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/OccupancyAggregatorConfig.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Core +{ + public class OccupancyAggregatorConfig + { + [JsonProperty("deviceKeys")] public List DeviceKeys { get; set; } + + OccupancyAggregatorConfig() + { + DeviceKeys = new List(); + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 3919d331..36992629 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -234,6 +234,7 @@ + From 9128e108f78eb671756228108e2b67fb3449744d Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 19 Jul 2021 15:09:03 -0600 Subject: [PATCH 12/14] feat: Add clear method to BoolOutputLogical and do a bit of refactoring --- .../Feedbacks/BoolOutputLogicals.cs | 66 ++++++++++--------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Feedbacks/BoolOutputLogicals.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Feedbacks/BoolOutputLogicals.cs index 3074254e..a8dae7b8 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Feedbacks/BoolOutputLogicals.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Feedbacks/BoolOutputLogicals.cs @@ -23,7 +23,7 @@ namespace PepperDash.Essentials.Core protected bool ComputedValue; - public BoolFeedbackLogic() + protected BoolFeedbackLogic() { Output = new BoolFeedback(() => ComputedValue); } @@ -40,21 +40,18 @@ namespace PepperDash.Essentials.Core public void AddOutputsIn(List outputs) { - foreach (var o in outputs) - { - // skip existing - if (OutputsIn.Contains(o)) continue; - - OutputsIn.Add(o); - o.OutputChange += AnyInput_OutputChange; - } - Evaluate(); + foreach (var o in outputs.Where(o => !OutputsIn.Contains(o))) + { + OutputsIn.Add(o); + o.OutputChange += AnyInput_OutputChange; + } + Evaluate(); } - public void RemoveOutputIn(BoolFeedback output) + public void RemoveOutputIn(BoolFeedback output) { // Don't double up outputs - if (OutputsIn.Contains(output)) return; + if (!OutputsIn.Contains(output)) return; OutputsIn.Remove(output); output.OutputChange -= AnyInput_OutputChange; @@ -71,6 +68,12 @@ namespace PepperDash.Essentials.Core Evaluate(); } + public void ClearOutputs() + { + OutputsIn.Clear(); + Evaluate(); + } + void AnyInput_OutputChange(object sender, EventArgs e) { Evaluate(); @@ -85,11 +88,12 @@ namespace PepperDash.Essentials.Core { var prevValue = ComputedValue; var newValue = OutputsIn.All(o => o.BoolValue); - if (newValue != prevValue) - { - ComputedValue = newValue; - Output.FireUpdate(); - } + if (newValue == prevValue) + { + return; + } + ComputedValue = newValue; + Output.FireUpdate(); } } @@ -99,33 +103,35 @@ namespace PepperDash.Essentials.Core { var prevValue = ComputedValue; var newValue = OutputsIn.Any(o => o.BoolValue); - if (newValue != prevValue) - { - ComputedValue = newValue; - Output.FireUpdate(); - } + if (newValue == prevValue) + { + return; + } + ComputedValue = newValue; + Output.FireUpdate(); } } public class BoolFeedbackLinq : BoolFeedbackLogic { - Func, bool> Predicate; + readonly Func, bool> _predicate; public BoolFeedbackLinq(Func, bool> predicate) : base() { - Predicate = predicate; + _predicate = predicate; } protected override void Evaluate() { var prevValue = ComputedValue; - var newValue = Predicate(OutputsIn); - if (newValue != prevValue) - { - ComputedValue = newValue; - Output.FireUpdate(); - } + var newValue = _predicate(OutputsIn); + if (newValue == prevValue) + { + return; + } + ComputedValue = newValue; + Output.FireUpdate(); } } } \ No newline at end of file From 10129b81782513de98f5cd8ab271c01affc4b25c Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 19 Jul 2021 15:09:37 -0600 Subject: [PATCH 13/14] feat: Add post activation action for aggregator --- .../IOccupancyStatusProviderAggregator.cs | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/IOccupancyStatusProviderAggregator.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/IOccupancyStatusProviderAggregator.cs index 601edf67..3da9c0dc 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/IOccupancyStatusProviderAggregator.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/IOccupancyStatusProviderAggregator.cs @@ -35,9 +35,38 @@ namespace PepperDash.Essentials.Core } public IOccupancyStatusProviderAggregator(string key, string name, OccupancyAggregatorConfig config) - : this(dc.Key, dc.Name) + : this(key, name) { - + AddPostActivationAction(() => + { + if (config.DeviceKeys.Count == 0) + { + return; + } + + foreach (var deviceKey in config.DeviceKeys) + { + var device = DeviceManager.GetDeviceForKey(deviceKey); + + if (device == null) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, + "Unable to retrieve Occupancy provider with key {0}", deviceKey); + continue; + } + + var provider = device as IOccupancyStatusProvider; + + if (provider == null) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, + "Device with key {0} does NOT implement IOccupancyStatusProvider. Please check configuration."); + continue; + } + + AddOccupancyStatusProvider(provider); + } + }); } /// @@ -52,6 +81,11 @@ namespace PepperDash.Essentials.Core public void RemoveOccupancyStatusProvider(IOccupancyStatusProvider statusProvider) { _aggregatedOccupancyStatus.RemoveOutputIn(statusProvider.RoomIsOccupiedFeedback); + } + + public void ClearOccupancyStatusProviders() + { + _aggregatedOccupancyStatus.ClearOutputs(); } } @@ -59,7 +93,7 @@ namespace PepperDash.Essentials.Core { public OccupancyAggregatorFactory() { - TypeNames = new List { "glsodtccn" }; + TypeNames = new List { "occupancyAggregator", "occAggregate" }; } From 45e6dff26d71e1b560845d3ba58e62b631bd52ee Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 19 Jul 2021 15:10:03 -0600 Subject: [PATCH 14/14] fix: update access level for config constructor --- .../Occupancy/OccupancyAggregatorConfig.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/OccupancyAggregatorConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/OccupancyAggregatorConfig.cs index 7909de04..ef237e72 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/OccupancyAggregatorConfig.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/OccupancyAggregatorConfig.cs @@ -7,7 +7,7 @@ namespace PepperDash.Essentials.Core { [JsonProperty("deviceKeys")] public List DeviceKeys { get; set; } - OccupancyAggregatorConfig() + public OccupancyAggregatorConfig() { DeviceKeys = new List(); }