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;
}
}
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 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 7d6acdc2..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
@@ -4,15 +4,20 @@ using System.Linq;
using System.Text;
using Crestron.SimplSharp;
+using PepperDash.Core;
+
+using Newtonsoft.Json;
+
namespace PepperDash.Essentials.Devices.Common.Codec
{
+ [Flags]
public enum eMeetingEventChangeType
{
- Unkown = 0,
- MeetingStartWarning,
- MeetingStart,
- MeetingEndWarning,
- MeetingEnd
+ Unknown = 0,
+ MeetingStartWarning = 1,
+ MeetingStart = 2,
+ MeetingEndWarning = 4,
+ MeetingEnd = 8
}
public interface IHasScheduleAwareness
@@ -32,6 +37,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; }
@@ -75,38 +84,72 @@ 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.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
+ 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);
changeType = eMeetingEventChangeType.MeetingStartWarning;
- else if (Math.Abs(m.TimeToMeetingStart.TotalMinutes) < meetingTimeEpsilon) // Meeting Start
+ }
+ else if (eMeetingEventChangeType.MeetingStart != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStart) && Math.Abs(m.TimeToMeetingStart.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 (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 (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.Unkown)
- OnMeetingChange(changeType, m);
+ if (changeType != eMeetingEventChangeType.Unknown)
+ {
+ OnMeetingChange(changeType, m);
+ }
}
-
}
}
@@ -115,17 +158,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 +183,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
return StartTime - DateTime.Now;
}
}
+ [JsonProperty("timeToMeetingEnd")]
public TimeSpan TimeToMeetingEnd
{
get
@@ -140,8 +191,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,21 +203,34 @@ namespace PepperDash.Essentials.Devices.Common.Codec
return EndTime - StartTime;
}
}
+ [JsonProperty("privacy")]
public eMeetingPrivacy Privacy { get; set; }
+ [JsonProperty("joinable")]
public bool Joinable
{
get
{
- return StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now
- && DateTime.Now <= EndTime; //.AddMinutes(-5);
+ 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; }
+ [JsonProperty("conferencePassword")]
public string ConferencePassword { get; set; }
+ [JsonProperty("isOneButtonToPushMeeting")]
public bool IsOneButtonToPushMeeting { get; set; }
+ [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 c4bfa298..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
@@ -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,12 +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();
+ _CodecSchedule = new CodecScheduleAwareness(1000);
for (int i = 0; i < 5; i++)
{
var m = new Meeting();
- m.StartTime = DateTime.Now.AddMinutes(3).AddHours(i);
- m.EndTime = DateTime.Now.AddHours(i).AddMinutes(30);
+ m.MinutesBeforeMeeting = 5;
+ m.Id = i.ToString();
+ m.Organizer = "Employee " + 1;
+ 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);