diff --git a/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo b/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo index b84c3a2c..0c3778c8 100644 Binary files a/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo and b/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo differ diff --git a/Essentials DM/Essentials_DM/Essentials_DM.projectinfo b/Essentials DM/Essentials_DM/Essentials_DM.projectinfo index 88bc6093..58baeaf5 100644 Binary files a/Essentials DM/Essentials_DM/Essentials_DM.projectinfo and b/Essentials DM/Essentials_DM/Essentials_DM.projectinfo differ diff --git a/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo b/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo index 5725875d..64d5ed77 100644 Binary files a/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo and b/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo differ diff --git a/Essentials/PepperDashEssentials/ControlSystem.cs b/Essentials/PepperDashEssentials/ControlSystem.cs index 381d83b1..a9808e15 100644 --- a/Essentials/PepperDashEssentials/ControlSystem.cs +++ b/Essentials/PepperDashEssentials/ControlSystem.cs @@ -40,7 +40,7 @@ namespace PepperDash.Essentials }, "listtielines", "Prints out all tie lines", ConsoleAccessLevelEnum.AccessOperator); - GoWithLoad(); + //GoWithLoad(); } /// diff --git a/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs b/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs index 6b79c2f7..29fc2643 100644 --- a/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs +++ b/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs @@ -11,6 +11,8 @@ using Crestron.SimplSharp.CrestronXmlLinq; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.Fusion; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using PepperDash.Essentials.Core; @@ -19,6 +21,7 @@ using PepperDash.Essentials; using PepperDash.Essentials.Devices.Common; + namespace PepperDash.Essentials.Fusion { public class EssentialsHuddleSpaceFusionSystemController : Device @@ -34,7 +37,17 @@ namespace PepperDash.Essentials.Fusion ScheduleResponse CurrentSchedule; - string GUID; + Event NextMeeting; + + Event CurrentMeeting; + + string RoomGuid; + + uint IpId; + + bool GuidFileExists; + + List StaticAssets; //ScheduleResponseEvent NextMeeting; @@ -43,44 +56,189 @@ namespace PepperDash.Essentials.Fusion { Room = room; + IpId = ipId; + + StaticAssets = new List(); + var mac = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0); var slot = Global.ControlSystem.ProgramNumber; - //adminvar guid = new Guid(); + string guidFilePath = string.Format(@"\NVRAM\Program{0}\{1}-FusionGuids.json", Global.ControlSystem.ProgramNumber, InitialParametersClass.ProgramIDTag); - GUID = string.Format("{0}-{1}-{2}", slot, mac, Room.Name.Replace(" ", String.Empty)); + GuidFileExists = File.Exists(guidFilePath); - CreateSymbolAndBasicSigs(ipId); + if (GuidFileExists) + { + ReadGuidFile(guidFilePath); + } + else + { + IpId = ipId; + + Guid roomGuid = Guid.NewGuid(); + + RoomGuid = string.Format("{0}-{1}-{2}", slot, mac, roomGuid.ToString()); + } + + CreateSymbolAndBasicSigs(IpId); SetUpSources(); SetUpCommunitcationMonitors(); SetUpDisplay(); SetUpError(); // test assets --- THESE ARE BOTH WIRED TO AssetUsage somewhere internally. - var ta1 = FusionRoom.CreateStaticAsset(1, "Test asset 1", "Awesome Asset", "Awesome123"); - ta1.AssetError.InputSig.StringValue = "This should be error"; + var tempAsset1 = new StaticAsset(); + var tempAsset2 = new StaticAsset(); - var ta2 = FusionRoom.CreateStaticAsset(2, "Test asset 2", "Awesome Asset", "Awesome1232"); - ta2.AssetUsage.InputSig.StringValue = "This should be usage"; + //Check for existing GUID + if (GuidFileExists) + { + tempAsset1 = StaticAssets.FirstOrDefault(a => a.Number.Equals(1)); - // Make it so! - FusionRVI.GenerateFileForAllFusionDevices(); + tempAsset2 = StaticAssets.FirstOrDefault(a => a.Number.Equals(2)); + } + else + { + tempAsset1 = new StaticAsset(1, "Test Asset 1", "Test Asset 1", ""); + StaticAssets.Add(tempAsset1); + + tempAsset2 = new StaticAsset(2, "Test Asset 2", "Test Asset 2", ""); + StaticAssets.Add(tempAsset2); + } + + var ta1 = FusionRoom.CreateStaticAsset(tempAsset1.Number, tempAsset1.Name, tempAsset1.Type, tempAsset1.InstanceID); + ta1.AssetError.InputSig.StringValue = "This should be error"; + + var ta2 = FusionRoom.CreateStaticAsset(tempAsset2.Number, tempAsset2.Name, tempAsset2.Type, tempAsset2.InstanceID); + ta2.AssetUsage.InputSig.StringValue = "This should be usage"; + + // Make it so! + FusionRVI.GenerateFileForAllFusionDevices(); + + GenerateGuidFile(guidFilePath); } + /// + /// Generates the guid file in NVRAM + /// + /// path for the file + void GenerateGuidFile(string filePath) + { + if (string.IsNullOrEmpty(filePath)) + { + Debug.Console(0, this, "Error writing guid file. No path specified."); + return; + } + + CCriticalSection _fileLock = new CCriticalSection(); + + try + { + if (_fileLock == null || _fileLock.Disposed) + return; + + _fileLock.Enter(); + + Debug.Console(1, this, "Writing GUIDs to file"); + + var GUIDs = new FusionRoomGuids(Room.Name, IpId, RoomGuid, StaticAssets); + + var JSON = JsonConvert.SerializeObject(GUIDs, Newtonsoft.Json.Formatting.Indented); + + using (StreamWriter sw = new StreamWriter(filePath)) + { + sw.Write(JSON); + sw.Flush(); + } + + Debug.Console(1, this, "Guids successfully written to file '{0}'", filePath); + + } + catch (Exception e) + { + Debug.Console(0, this, "Error writing guid file: {0}", e); + } + finally + { + if (_fileLock != null && !_fileLock.Disposed) + _fileLock.Leave(); + } + } + + /// + /// Reads the guid file from NVRAM + /// + /// path for te file + void ReadGuidFile(string filePath) + { + if(string.IsNullOrEmpty(filePath)) + { + Debug.Console(0, this, "Error reading guid file. No path specified."); + return; + } + + CCriticalSection _fileLock = new CCriticalSection(); + + try + { + if(_fileLock == null || _fileLock.Disposed) + return; + + _fileLock.Enter(); + + if(File.Exists(filePath)) + { + var JSON = File.ReadToEnd(filePath, Encoding.ASCII); + + var GUIDs = JsonConvert.DeserializeObject(JSON); + + IpId = GUIDs.IpId; + + RoomGuid = GUIDs.RoomGuid; + + StaticAssets = GUIDs.StaticAssets; + + } + + Debug.Console(0, this, "Fusion Guids successfully read from file:"); + + Debug.Console(1, this, "\nRoom Name: {0}\nIPID: {1}\n RoomGuid: {2}", Room.Name, IpId, RoomGuid); + + foreach (StaticAsset asset in StaticAssets) + { + Debug.Console(1, this, "\nAsset Name: {0}\nAsset No: {1}\n Guid: {2}", asset.Name, asset.Number, asset.InstanceID); + } + } + catch (Exception e) + { + Debug.Console(0, this, "Error reading guid file: {0}", e); + } + finally + { + if(_fileLock != null && !_fileLock.Disposed) + _fileLock.Leave(); + } + + } + + void CreateSymbolAndBasicSigs(uint ipId) { - Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", GUID); + Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", RoomGuid); - FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, GUID); + FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid); FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use(); + FusionRoom.ExtenderFusionRoomDataReservedSigs.Use(); FusionRoom.Register(); - FusionRoom.FusionStateChange += new FusionStateEventHandler(FusionRoom_FusionStateChange); + FusionRoom.FusionStateChange += new FusionStateEventHandler(FusionRoom_FusionStateChange); FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += new DeviceExtenderJoinChangeEventHandler(FusionRoomSchedule_DeviceExtenderSigChange); + FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += new DeviceExtenderJoinChangeEventHandler(ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange); + FusionRoom.OnlineStatusChange += new OnlineStatusChangeEventHandler(FusionRoom_OnlineStatusChange); CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator); @@ -98,33 +256,57 @@ namespace PepperDash.Essentials.Fusion FusionRoom.ErrorMessage.InputSig.StringValue = "3: 7 Errors: This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;"; + } + void FusionRoom_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args) + { + if (args.DeviceOnLine) + { + // Send Push Notification Action request: + + string requestID = "InitialPushRequest"; + + + string actionRequest = + string.Format("{0}{1}", requestID, RoomGuid) + + "RegisterPushModel" + + "" + + "" + + "" + + "" + + "" + + "'"; + + Debug.Console(1, this, "Sending Fusion ScheduleQuery: \n{0}", actionRequest); + + FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = actionRequest; + } + + } + + /// /// Generates a room schedule request for this room for the next 24 hours. /// /// string identifying this request. Used with a corresponding ScheduleResponse value public void RequestFullRoomSchedule(string requestID) { - //Need to see if we can omit the XML declaration + DateTime now = DateTime.Today; - //XmlWriterSettings settings = new XmlWriterSettings(); - //settings.OmitXmlDeclaration = true; + //string currentTime = string.Format("Current time: {0:D4}-{1:D2}-{2:D2}T{3:D2}:{4:D2}:{5:D2}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); - //StringBuilder builder = new StringBuilder(); + string currentTime = now.ToString("s"); - //XmlWriter xmlWriter = new XmlWriter(builder, settings); + Debug.Console(1, this, "Current time: {0}", currentTime); - //RequestSchedule request = new RequestSchedule(requestID, GUID); + //Debug.Console(1, this, "Current time: {0}", now.ToString("d")); - //CrestronXMLSerialization.SerializeObject(xmlWriter, request); - - DateTime now = DateTime.UtcNow; - - Debug.Console(1, this, "Current time: {0}-{1}-{2}T{3}:{4}:{5}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); + //string requestTest = + // string.Format("{0}{1}2017-05-02T00:00:0024", requestID, GUID); string requestTest = - string.Format("{0}{1}2017-05-02T00:00:0024", requestID, GUID); + string.Format("{0}{1}{2}24", requestID, RoomGuid, currentTime); Debug.Console(1, this, "Sending Fusion ScheduleQuery: \n{0}", requestTest); @@ -170,103 +352,114 @@ namespace PepperDash.Essentials.Fusion /// Number of minutes to extend the meeting. A value of 0 will end the meeting. public void ModifyMeetingEndTime(string requestID, PepperDash.Essentials.Fusion.Event meeting, int extendMinutes) { - //StringWriter stringWriter = new StringWriter(); - - //List parameters = new List(); - - //parameters.Add( new Parameter { ID = "MeetingID", Value = meeting.MeetingID }); - - //parameters.Add( new Parameter { ID = "EndTime", Value = extendMinutes.ToString()}); - - //RequestAction request = new RequestAction(GUID, "MeetingChange", parameters); - - //CrestronXMLSerialization.SerializeObject(stringWriter, request); - string requestTest = string.Format( - "{0}{1}MeetingChange" - , requestID, GUID, meeting.MeetingID, extendMinutes); + "{0}{1}MeetingChange" + , requestID, RoomGuid, meeting.MeetingID, extendMinutes); Debug.Console(1, this, "Sending MeetingChange Request: \n{0}", requestTest); - FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleQuery.StringValue = requestTest; + //FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleQuery.StringValue = requestTest; + + FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = requestTest; } - void FusionRoomSchedule_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) + + void ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) { Debug.Console(1, this, "Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue); - if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleResponse) + if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQueryResponse) { try - { - ScheduleResponse scheduleResponse = new ScheduleResponse(); - - XmlDocument message = new XmlDocument(); - - message.LoadXml(args.Sig.StringValue); - - if (message.FirstChild.Name == "ScheduleResponse") - { - foreach (XmlElement element in message.FirstChild.ChildNodes) - { - if (element.Name == "RequestID") - { - scheduleResponse.RequestID = element.InnerText; - } - else if (element.Name == "RoomID") - { - scheduleResponse.RoomID = element.InnerText; - } - else if (element.Name == "RoomName") - { - scheduleResponse.RoomName = element.InnerText; - } - else if (element.Name == "Event") - { - Debug.Console(1, this, "Event Found:\n{0}", element.OuterXml); - - XmlReader reader = new XmlReader(element.OuterXml); - - Event tempEvent = new Event(); - - tempEvent = CrestronXMLSerialization.DeSerializeObject(reader); - - scheduleResponse.Events.Add(tempEvent); - } - - } - } - - //XmlReader reader = new XmlReader(args.Sig.StringValue); - - //scheduleResponse = CrestronXMLSerialization.DeSerializeObject(reader); - - //Debug.Console(1, this, "ScheduleResponse DeSerialization Successful for Room: '{0}'", scheduleResponse.RoomName); - - if (scheduleResponse.Events.Count > 0) - { - Debug.Console(1, this, "Meetings Count: {0}\n", scheduleResponse.Events.Count); - - foreach (Event e in scheduleResponse.Events) - { - Debug.Console(1, this, "Subject: {0}", e.Subject); - Debug.Console(1, this, "MeetingID: {0}", e.MeetingID); - Debug.Console(1, this, "Start Time: {0}", e.dtStart); - Debug.Console(1, this, "End Time: {0}\n", e.dtEnd); - } - } - - CurrentSchedule = scheduleResponse; + { } catch (Exception e) { - Debug.Console(1, this, "Error parsing ScheduleResponse: {0}", e); + Debug.Console(1, this, "Error parsing ActionQueryResponse: {0}", e); } } } + void FusionRoomSchedule_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) + { + Debug.Console(1, this, "Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue); + + + if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleResponse) + { + try + { + ScheduleResponse scheduleResponse = new ScheduleResponse(); + + XmlDocument message = new XmlDocument(); + + message.LoadXml(args.Sig.StringValue); + + if (message.FirstChild.Name == "ScheduleResponse") + { + foreach (XmlElement element in message.FirstChild.ChildNodes) + { + if (element.Name == "RequestID") + { + scheduleResponse.RequestID = element.InnerText; + } + else if (element.Name == "RoomID") + { + scheduleResponse.RoomID = element.InnerText; + } + else if (element.Name == "RoomName") + { + scheduleResponse.RoomName = element.InnerText; + } + else if (element.Name == "Event") + { + Debug.Console(1, this, "Event Found:\n{0}", element.OuterXml); + + XmlReader reader = new XmlReader(element.OuterXml); + + Event tempEvent = new Event(); + + tempEvent = CrestronXMLSerialization.DeSerializeObject(reader); + + scheduleResponse.Events.Add(tempEvent); + } + + } + } + + //XmlReader reader = new XmlReader(args.Sig.StringValue); + + //scheduleResponse = CrestronXMLSerialization.DeSerializeObject(reader); + + //Debug.Console(1, this, "ScheduleResponse DeSerialization Successful for Room: '{0}'", scheduleResponse.RoomName); + + if (scheduleResponse.Events.Count > 0) + { + Debug.Console(1, this, "Meetings Count: {0}\n", scheduleResponse.Events.Count); + + foreach (Event e in scheduleResponse.Events) + { + Debug.Console(1, this, "Subject: {0}", e.Subject); + Debug.Console(1, this, "MeetingID: {0}", e.MeetingID); + Debug.Console(1, this, "Start Time: {0}", e.dtStart); + Debug.Console(1, this, "End Time: {0}\n", e.dtEnd); + var duration = e.dtEnd.Subtract(e.dtStart); + Debug.Console(1, this, "Duration: {0} minutes", duration.Minutes); + } + } + + CurrentSchedule = scheduleResponse; + + } + catch (Exception e) + { + Debug.Console(1, this, "Error parsing ScheduleResponse: {0}", e); + } + } + } + void SetUpSources() { // Sources @@ -420,7 +613,16 @@ namespace PepperDash.Essentials.Fusion // static assets --------------- testing // Make a display asset - var dispAsset = FusionRoom.CreateStaticAsset(3, display.Name, "Display", "awesomeDisplayId" + Room.Key); + string dispAssetInstanceId; + + //Check for existing GUID + var tempAsset = StaticAssets.FirstOrDefault(a => a.Number.Equals(3)); + if(tempAsset != null) + dispAssetInstanceId = tempAsset.InstanceID; + else + dispAssetInstanceId = ""; + + var dispAsset = FusionRoom.CreateStaticAsset(3, display.Name, "Display", dispAssetInstanceId); dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction; dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction; display.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig); @@ -576,7 +778,12 @@ namespace PepperDash.Essentials.Fusion /// /// the new asset public static FusionStaticAsset CreateStaticAsset(this FusionRoom fr, uint number, string name, string type, string instanceId) - { + { + //if(string.IsNullOrEmpty(instanceId)) + // instanceId = Guid.NewGuid().ToString(); + + Debug.Console(0, "Creating Fusion Static Asset '{0}' with GUID: '{1}'", name, instanceId); + fr.AddAsset(eAssetType.StaticAsset, number, name, type, instanceId); return fr.UserConfigurableAssetDetails[number].Asset as FusionStaticAsset; } @@ -628,6 +835,56 @@ namespace PepperDash.Essentials.Fusion } } + // Helper Classes for GUIDs + + /// + /// Stores GUIDs to be written to a file in NVRAM + /// + public class FusionRoomGuids + { + public string RoomName { get; set; } + public uint IpId { get; set; } + public string RoomGuid { get; set; } + public List StaticAssets { get; set; } + + public FusionRoomGuids(string roomName, uint ipId, string roomGuid, List staticAssets) + { + RoomName = roomName; + IpId = ipId; + RoomGuid = roomGuid; + + StaticAssets = new List(staticAssets); + } + } + + public class StaticAsset + { + public uint Number { get; set; } + public string Name { get; set; } + public string Type { get; set; } + public string InstanceID { get; set; } + + public StaticAsset() + { + + } + + public StaticAsset(uint slotNum, string assetName, string type, string instanceID) + { + Number = slotNum; + Name = assetName; + Type = type; + if(string.IsNullOrEmpty(instanceID)) + { + InstanceID = Guid.NewGuid().ToString(); + } + else + { + InstanceID = instanceID; + } + } + } + //**************************************************************************************************** // Helper Classes for XML API diff --git a/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo b/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo index 3503082a..d3ee2011 100644 Binary files a/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo and b/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo differ