diff --git a/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs b/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs
index f4a99b04..361697da 100644
--- a/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs
+++ b/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs
@@ -100,6 +100,12 @@ namespace PepperDash.Essentials.Devices.Common
return new Laptop(key, name);
}
+ else if (typeName == "mockvc")
+ {
+ return new PepperDash.Essentials.Devices.Common.VideoCodec
+ .MockVC(key, name);
+ }
+
else if (groupName == "settopbox") //(typeName == "irstbbase")
{
var irCont = IRPortHelper.GetIrOutputPortController(dc);
diff --git a/Essentials Devices Common/Essentials Devices Common/VC/MockVC/MockVC.cs b/Essentials Devices Common/Essentials Devices Common/VC/MockVC/MockVC.cs
index d8f11150..29b5832c 100644
--- a/Essentials Devices Common/Essentials Devices Common/VC/MockVC/MockVC.cs
+++ b/Essentials Devices Common/Essentials Devices Common/VC/MockVC/MockVC.cs
@@ -52,7 +52,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
///
public override void Dial(string s)
{
-
+ Debug.Console(1, this, "Dial: {0}", s);
+
_InCall = true;
InCallFeedback.FireUpdate();
}
@@ -63,12 +64,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
///
public void SendDTMF(string s)
{
-
+ Debug.Console(1, this, "SendDTMF: {0}", s);
}
-
+ ///
+ ///
+ ///
public override void EndCall()
{
+ Debug.Console(1, this, "EndCall");
_InCall = false;
InCallFeedback.FireUpdate();
}
@@ -78,7 +82,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
///
public override void AcceptCall()
{
-
+ Debug.Console(1, this, "AcceptCall");
}
///
@@ -86,52 +90,84 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
///
public override void RejectCall()
{
-
+ Debug.Console(1, this, "RejectCall");
}
-
+ ///
+ /// Called by routing to make it happen
+ ///
+ ///
public override void ExecuteSwitch(object selector)
{
-
+ Debug.Console(1, this, "ExecuteSwitch");
+
}
+ ///
+ ///
+ ///
public override void ReceiveMuteOff()
{
+ Debug.Console(1, this, "ReceiveMuteOff");
+
if (!_ReceiveMute)
return;
_ReceiveMute = false;
ReceiveMuteIsOnFeedback.FireUpdate();
}
+ ///
+ ///
+ ///
public override void ReceiveMuteOn()
{
+ Debug.Console(1, this, "ReceiveMuteOn");
if (_ReceiveMute)
return;
ReceiveMuteIsOnFeedback.FireUpdate();
}
+ ///
+ ///
+ ///
public override void ReceiveMuteToggle()
{
+ Debug.Console(1, this, "ReceiveMuteToggle");
+
_ReceiveMute = !_ReceiveMute;
ReceiveMuteIsOnFeedback.FireUpdate();
}
+ ///
+ ///
+ ///
+ ///
public override void SetReceiveVolume(ushort level)
{
-
+ Debug.Console(1, this, "SetReceiveVolume: {0}", level);
+
}
+ ///
+ ///
+ ///
public override void TransmitMuteOff()
{
+ Debug.Console(1, this, "TransmitMuteOff");
+
if (!_TransmitMute)
return;
_TransmitMute = false;
TransmitMuteIsOnFeedback.FireUpdate();
}
+ ///
+ ///
+ ///
public override void TransmitMuteOn()
{
+ Debug.Console(1, this, "TransmitMuteOn");
if (_TransmitMute)
return;
TransmitMuteIsOnFeedback.FireUpdate();
@@ -140,16 +176,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
public override void TransmitMuteToggle()
{
_TransmitMute = !_TransmitMute;
+ Debug.Console(1, this, "TransmitMuteToggle: {0}", _TransmitMute);
TransmitMuteIsOnFeedback.FireUpdate();
}
public override void SetTransmitVolume(ushort level)
{
-
+ Debug.Console(1, this, "SetTransmitVolume: {0}", level);
}
public override void PrivacyModeOn()
{
+ Debug.Console(1, this, "PrivacyMuteOn");
if (_PrivacyModeIsOn)
return;
_PrivacyModeIsOn = true;
@@ -159,6 +197,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
public override void PrivacyModeOff()
{
+ Debug.Console(1, this, "PrivacyMuteOff");
if (!_PrivacyModeIsOn)
return;
_PrivacyModeIsOn = false;
@@ -168,7 +207,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
public override void PrivacyModeToggle()
{
_PrivacyModeIsOn = !_PrivacyModeIsOn;
- PrivacyModeIsOnFeedback.FireUpdate();
+ Debug.Console(1, this, "PrivacyMuteToggle: {0}", _PrivacyModeIsOn);
+ PrivacyModeIsOnFeedback.FireUpdate();
}
//********************************************************
@@ -176,16 +216,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
public void TestIncomingCall(string url)
{
+ Debug.Console(1, this, "TestIncomingCall");
+
_IncomingCall = true;
IncomingCallFeedback.FireUpdate();
}
public void TestFarEndHangup()
{
+ Debug.Console(1, this, "TestFarEndHangup");
}
-
-
-
}
}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Config/DeviceFactory.cs b/Essentials/PepperDashEssentials/Config/DeviceFactory.cs
index d87e41b7..7a8dfdb9 100644
--- a/Essentials/PepperDashEssentials/Config/DeviceFactory.cs
+++ b/Essentials/PepperDashEssentials/Config/DeviceFactory.cs
@@ -35,6 +35,7 @@ namespace PepperDash.Essentials
properties.ToString());
return new EssentialsTouchpanelController(key, name, typeName, props, comm.IpIdInt);
}
+
else if (typeName == "mockdisplay")
{
return new MockDisplay(key, name);
diff --git a/Essentials/PepperDashEssentials/Fusion/FusionEventHandlers.cs b/Essentials/PepperDashEssentials/OTHER/Fusion/FusionEventHandlers.cs
similarity index 95%
rename from Essentials/PepperDashEssentials/Fusion/FusionEventHandlers.cs
rename to Essentials/PepperDashEssentials/OTHER/Fusion/FusionEventHandlers.cs
index 7c7b5168..4987c047 100644
--- a/Essentials/PepperDashEssentials/Fusion/FusionEventHandlers.cs
+++ b/Essentials/PepperDashEssentials/OTHER/Fusion/FusionEventHandlers.cs
@@ -1,18 +1,18 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-
-namespace PepperDash.Essentials.Fusion
-{
- public class ScheduleChangeEventArgs : EventArgs
- {
- public RoomSchedule Schedule { get; set; }
- }
-
- public class MeetingChangeEventArgs : EventArgs
- {
- public Event Meeting { get; set; }
- }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+
+namespace PepperDash.Essentials.Fusion
+{
+ public class ScheduleChangeEventArgs : EventArgs
+ {
+ public RoomSchedule Schedule { get; set; }
+ }
+
+ public class MeetingChangeEventArgs : EventArgs
+ {
+ public Event Meeting { get; set; }
+ }
}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Fusion/FusionProcessorQueries.cs b/Essentials/PepperDashEssentials/OTHER/Fusion/FusionProcessorQueries.cs
similarity index 97%
rename from Essentials/PepperDashEssentials/Fusion/FusionProcessorQueries.cs
rename to Essentials/PepperDashEssentials/OTHER/Fusion/FusionProcessorQueries.cs
index 9781fe08..8757be62 100644
--- a/Essentials/PepperDashEssentials/Fusion/FusionProcessorQueries.cs
+++ b/Essentials/PepperDashEssentials/OTHER/Fusion/FusionProcessorQueries.cs
@@ -1,63 +1,63 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-using PepperDash.Core;
-using PepperDash.Essentials.Core;
-
-namespace PepperDash.Essentials.Fusion
-{
- ///
- /// When created, runs progcomments on every slot and stores the program names in a list
- ///
- public class ProcessorProgReg
- {
- //public static Dictionary Programs { get; private set; }
-
- public static Dictionary GetProcessorProgReg()
- {
- var programs = new Dictionary();
- for (int i = 1; i <= Global.ControlSystem.NumProgramsSupported; i++)
- {
- string response = null;
- var success = CrestronConsole.SendControlSystemCommand("progcomments:" + i, ref response);
- var item = new ProcessorProgramItem();
- if (!success)
- item.Name = "Error: PROGCOMMENTS failed";
- else
- {
- if (response.ToLower().Contains("bad or incomplete"))
- item.Name = "";
- else
- {
- var startPos = response.IndexOf("Program File");
- var colonPos = response.IndexOf(":", startPos) + 1;
- var endPos = response.IndexOf(CrestronEnvironment.NewLine, colonPos);
- item.Name = response.Substring(colonPos, endPos - colonPos).Trim();
- item.Exists = true;
- if (item.Name.Contains(".dll"))
- {
- startPos = response.IndexOf("Compiler Revision");
- colonPos = response.IndexOf(":", startPos) + 1;
- endPos = response.IndexOf(CrestronEnvironment.NewLine, colonPos);
- item.Name = item.Name + "_v" + response.Substring(colonPos, endPos - colonPos).Trim();
- }
- }
- }
- programs[i] = item;
- Debug.Console(1, "Program {0}: {1}", i, item.Name);
- }
- return programs;
- }
- }
-
- ///
- /// Used in ProcessorProgReg
- ///
- public class ProcessorProgramItem
- {
- public bool Exists { get; set; }
- public string Name { get; set; }
- }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+
+namespace PepperDash.Essentials.Fusion
+{
+ ///
+ /// When created, runs progcomments on every slot and stores the program names in a list
+ ///
+ public class ProcessorProgReg
+ {
+ //public static Dictionary Programs { get; private set; }
+
+ public static Dictionary GetProcessorProgReg()
+ {
+ var programs = new Dictionary();
+ for (int i = 1; i <= Global.ControlSystem.NumProgramsSupported; i++)
+ {
+ string response = null;
+ var success = CrestronConsole.SendControlSystemCommand("progcomments:" + i, ref response);
+ var item = new ProcessorProgramItem();
+ if (!success)
+ item.Name = "Error: PROGCOMMENTS failed";
+ else
+ {
+ if (response.ToLower().Contains("bad or incomplete"))
+ item.Name = "";
+ else
+ {
+ var startPos = response.IndexOf("Program File");
+ var colonPos = response.IndexOf(":", startPos) + 1;
+ var endPos = response.IndexOf(CrestronEnvironment.NewLine, colonPos);
+ item.Name = response.Substring(colonPos, endPos - colonPos).Trim();
+ item.Exists = true;
+ if (item.Name.Contains(".dll"))
+ {
+ startPos = response.IndexOf("Compiler Revision");
+ colonPos = response.IndexOf(":", startPos) + 1;
+ endPos = response.IndexOf(CrestronEnvironment.NewLine, colonPos);
+ item.Name = item.Name + "_v" + response.Substring(colonPos, endPos - colonPos).Trim();
+ }
+ }
+ }
+ programs[i] = item;
+ Debug.Console(1, "Program {0}: {1}", i, item.Name);
+ }
+ return programs;
+ }
+ }
+
+ ///
+ /// Used in ProcessorProgReg
+ ///
+ public class ProcessorProgramItem
+ {
+ public bool Exists { get; set; }
+ public string Name { get; set; }
+ }
}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Fusion/FusionRviDataClasses.cs b/Essentials/PepperDashEssentials/OTHER/Fusion/FusionRviDataClasses.cs
similarity index 96%
rename from Essentials/PepperDashEssentials/Fusion/FusionRviDataClasses.cs
rename to Essentials/PepperDashEssentials/OTHER/Fusion/FusionRviDataClasses.cs
index e08d806f..3752531a 100644
--- a/Essentials/PepperDashEssentials/Fusion/FusionRviDataClasses.cs
+++ b/Essentials/PepperDashEssentials/OTHER/Fusion/FusionRviDataClasses.cs
@@ -1,499 +1,499 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-using Crestron.SimplSharpPro.Fusion;
-
-using PepperDash.Core;
-
-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 FusionOccupancySensorAsset OccupancyAsset { get; set; }
- public Dictionary StaticAssets { get; set; }
-
- public FusionRoomGuids()
- {
- StaticAssets = new Dictionary();
- OccupancyAsset = new FusionOccupancySensorAsset();
- }
-
- public FusionRoomGuids(string roomName, uint ipId, string roomGuid, Dictionary staticAssets)
- {
- RoomName = roomName;
- IpId = ipId;
- RoomGuid = roomGuid;
-
- StaticAssets = staticAssets;
- OccupancyAsset = new FusionOccupancySensorAsset();
- }
-
- public FusionRoomGuids(string roomName, uint ipId, string roomGuid, Dictionary staticAssets, FusionOccupancySensorAsset occAsset)
- {
- RoomName = roomName;
- IpId = ipId;
- RoomGuid = roomGuid;
-
- StaticAssets = staticAssets;
- OccupancyAsset = occAsset;
- }
-
- ///
- /// Generates a new room GUID prefixed by the program slot number and NIC MAC address
- ///
- ///
- ///
- public string GenerateNewRoomGuid(uint progSlot, string mac)
- {
- Guid roomGuid = Guid.NewGuid();
-
- return string.Format("{0}-{1}-{2}", progSlot, mac, roomGuid.ToString());
- }
-
-
- ///
- /// Adds an asset to the StaticAssets collection and returns the new asset
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public FusionAsset AddStaticAsset(FusionRoom room, int uid, string assetName, string type, string instanceId)
- {
- var slotNum = GetNextAvailableAssetNumber(room);
-
- Debug.Console(2, "Adding Fusion Asset: {0} of Type: {1} at Slot Number: {2} with GUID: {3}", assetName, type, slotNum, instanceId);
-
- var tempAsset = new FusionAsset(slotNum, assetName, type, instanceId);
-
- StaticAssets.Add(uid, tempAsset);
-
- return tempAsset;
- }
-
- ///
- /// Returns the next available slot number in the Fusion UserConfigurableAssetDetails collection
- ///
- ///
- ///
- public static uint GetNextAvailableAssetNumber(FusionRoom room)
- {
- uint slotNum = 0;
-
- foreach (var item in room.UserConfigurableAssetDetails)
- {
- if(item.Number > slotNum)
- slotNum = item.Number;
- }
-
- if (slotNum < 5)
- {
- slotNum = 5;
- }
- else
- slotNum = slotNum + 1;
-
- Debug.Console(2, "#Next available fusion asset number is: {0}", slotNum);
-
- return slotNum;
- }
-
- }
-
- public class FusionOccupancySensorAsset
- {
- // SlotNumber fixed at 4
-
- public uint SlotNumber { get { return 4; } }
- public string Name { get { return "Occupancy Sensor"; } }
- public eAssetType Type { get; set; }
- public string InstanceId { get; set; }
-
- public FusionOccupancySensorAsset()
- {
- }
-
- public FusionOccupancySensorAsset(eAssetType type)
- {
- Type = type;
-
- InstanceId = Guid.NewGuid().ToString();
- }
- }
-
- public class FusionAsset
- {
- public uint SlotNumber { get; set; }
- public string Name { get; set; }
- public string Type { get; set; }
- public string InstanceId { get;set; }
-
- public FusionAsset()
- {
-
- }
-
- public FusionAsset(uint slotNum, string assetName, string type, string instanceId)
- {
- SlotNumber = slotNum;
- Name = assetName;
- Type = type;
- if (string.IsNullOrEmpty(instanceId))
- {
- InstanceId = Guid.NewGuid().ToString();
- }
- else
- {
- InstanceId = instanceId;
- }
- }
- }
-
- //***************************************************************************************************
-
- public class RoomSchedule
- {
- public List Meetings { get; set; }
-
- public RoomSchedule()
- {
- Meetings = new List();
- }
- }
-
- //****************************************************************************************************
- // Helper Classes for XML API
-
- ///
- /// Data needed to request the local time from the Fusion server
- ///
- public class LocalTimeRequest
- {
- public string RequestID { get; set; }
- }
-
- ///
- /// All the data needed for a full schedule request in a room
- ///
- /// //[XmlRoot(ElementName = "RequestSchedule")]
- public class RequestSchedule
- {
- //[XmlElement(ElementName = "RequestID")]
- public string RequestID { get; set; }
- //[XmlElement(ElementName = "RoomID")]
- public string RoomID { get; set; }
- //[XmlElement(ElementName = "Start")]
- public DateTime Start { get; set; }
- //[XmlElement(ElementName = "HourSpan")]
- public double HourSpan { get; set; }
-
- public RequestSchedule(string requestID, string roomID)
- {
- RequestID = requestID;
- RoomID = roomID;
- Start = DateTime.Now;
- HourSpan = 24;
- }
- }
-
-
- //[XmlRoot(ElementName = "RequestAction")]
- public class RequestAction
- {
- //[XmlElement(ElementName = "RequestID")]
- public string RequestID { get; set; }
- //[XmlElement(ElementName = "RoomID")]
- public string RoomID { get; set; }
- //[XmlElement(ElementName = "ActionID")]
- public string ActionID { get; set; }
- //[XmlElement(ElementName = "Parameters")]
- public List Parameters { get; set; }
-
- public RequestAction(string roomID, string actionID, List parameters)
- {
- RoomID = roomID;
- ActionID = actionID;
- Parameters = parameters;
- }
- }
-
- //[XmlRoot(ElementName = "ActionResponse")]
- public class ActionResponse
- {
- //[XmlElement(ElementName = "RequestID")]
- public string RequestID { get; set; }
- //[XmlElement(ElementName = "ActionID")]
- public string ActionID { get; set; }
- //[XmlElement(ElementName = "Parameters")]
- public List Parameters { get; set; }
- }
-
- //[XmlRoot(ElementName = "Parameter")]
- public class Parameter
- {
- //[XmlAttribute(AttributeName = "ID")]
- public string ID { get; set; }
- //[XmlAttribute(AttributeName = "Value")]
- public string Value { get; set; }
- }
-
- ////[XmlRoot(ElementName = "Parameters")]
- //public class Parameters
- //{
- // //[XmlElement(ElementName = "Parameter")]
- // public List Parameter { get; set; }
- //}
-
- ///
- /// Data structure for a ScheduleResponse from Fusion
- ///
- /// //[XmlRoot(ElementName = "ScheduleResponse")]
- public class ScheduleResponse
- {
- //[XmlElement(ElementName = "RequestID")]
- public string RequestID { get; set; }
- //[XmlElement(ElementName = "RoomID")]
- public string RoomID { get; set; }
- //[XmlElement(ElementName = "RoomName")]
- public string RoomName { get; set; }
- //[XmlElement("Event")]
- public List Events { get; set; }
-
- public ScheduleResponse()
- {
- Events = new List();
- }
- }
-
- //[XmlRoot(ElementName = "Event")]
- public class Event
- {
- //[XmlElement(ElementName = "MeetingID")]
- public string MeetingID { get; set; }
- //[XmlElement(ElementName = "RVMeetingID")]
- public string RVMeetingID { get; set; }
- //[XmlElement(ElementName = "Recurring")]
- public string Recurring { get; set; }
- //[XmlElement(ElementName = "InstanceID")]
- public string InstanceID { get; set; }
- //[XmlElement(ElementName = "dtStart")]
- public DateTime dtStart { get; set; }
- //[XmlElement(ElementName = "dtEnd")]
- public DateTime dtEnd { get; set; }
- //[XmlElement(ElementName = "Organizer")]
- public string Organizer { get; set; }
- //[XmlElement(ElementName = "Attendees")]
- public Attendees Attendees { get; set; }
- //[XmlElement(ElementName = "Resources")]
- public Resources Resources { get; set; }
- //[XmlElement(ElementName = "IsEvent")]
- public string IsEvent { get; set; }
- //[XmlElement(ElementName = "IsRoomViewMeeting")]
- public string IsRoomViewMeeting { get; set; }
- //[XmlElement(ElementName = "IsPrivate")]
- public string IsPrivate { get; set; }
- //[XmlElement(ElementName = "IsExchangePrivate")]
- public string IsExchangePrivate { get; set; }
- //[XmlElement(ElementName = "MeetingTypes")]
- public MeetingTypes MeetingTypes { get; set; }
- //[XmlElement(ElementName = "ParticipantCode")]
- public string ParticipantCode { get; set; }
- //[XmlElement(ElementName = "PhoneNo")]
- public string PhoneNo { get; set; }
- //[XmlElement(ElementName = "WelcomeMsg")]
- public string WelcomeMsg { get; set; }
- //[XmlElement(ElementName = "Subject")]
- public string Subject { get; set; }
- //[XmlElement(ElementName = "LiveMeeting")]
- public LiveMeeting LiveMeeting { get; set; }
- //[XmlElement(ElementName = "ShareDocPath")]
- public string ShareDocPath { get; set; }
- //[XmlElement(ElementName = "HaveAttendees")]
- public string HaveAttendees { get; set; }
- //[XmlElement(ElementName = "HaveResources")]
- public string HaveResources { get; set; }
-
- ///
- /// Gets the duration of the meeting
- ///
- public string DurationInMinutes
- {
- get
- {
- string duration;
-
- var timeSpan = dtEnd.Subtract(dtStart);
- int hours = timeSpan.Hours;
- double minutes = timeSpan.Minutes;
- double roundedMinutes = Math.Round(minutes);
- if (hours > 0)
- {
- duration = string.Format("{0} hours {1} minutes", hours, roundedMinutes);
- }
- else
- {
- duration = string.Format("{0} minutes", roundedMinutes);
- }
-
- return duration;
- }
- }
-
- ///
- /// Gets the remaining time in the meeting. Returns null if the meeting is not currently in progress.
- ///
- public string RemainingTime
- {
- get
- {
- var now = DateTime.Now;
-
- string remainingTime;
-
- if (GetInProgress())
- {
- var timeSpan = dtEnd.Subtract(now);
- int hours = timeSpan.Hours;
- double minutes = timeSpan.Minutes;
- double roundedMinutes = Math.Round(minutes);
- if (hours > 0)
- {
- remainingTime = string.Format("{0} hours {1} minutes", hours, roundedMinutes);
- }
- else
- {
- remainingTime = string.Format("{0} minutes", roundedMinutes);
- }
-
- return remainingTime;
- }
- else
- return null;
- }
-
- }
-
- ///
- /// Indicates that the meeting is in progress
- ///
- public bool isInProgress
- {
- get
- {
- return GetInProgress();
- }
- }
-
- ///
- /// Determines if the meeting is in progress
- ///
- /// Returns true if in progress
- bool GetInProgress()
- {
- var now = DateTime.Now;
-
- if (now > dtStart && now < dtEnd)
- {
- return true;
- }
- else
- return false;
- }
- }
-
- //[XmlRoot(ElementName = "Resources")]
- public class Resources
- {
- //[XmlElement(ElementName = "Rooms")]
- public Rooms Rooms { get; set; }
- }
-
- //[XmlRoot(ElementName = "Rooms")]
- public class Rooms
- {
- //[XmlElement(ElementName = "Room")]
- public List Room { get; set; }
- }
-
- //[XmlRoot(ElementName = "Room")]
- public class Room
- {
- //[XmlElement(ElementName = "Name")]
- public string Name { get; set; }
- //[XmlElement(ElementName = "ID")]
- public string ID { get; set; }
- //[XmlElement(ElementName = "MPType")]
- public string MPType { get; set; }
- }
-
- //[XmlRoot(ElementName = "Attendees")]
- public class Attendees
- {
- //[XmlElement(ElementName = "Required")]
- public Required Required { get; set; }
- //[XmlElement(ElementName = "Optional")]
- public Optional Optional { get; set; }
- }
-
- //[XmlRoot(ElementName = "Required")]
- public class Required
- {
- //[XmlElement(ElementName = "Attendee")]
- public List Attendee { get; set; }
- }
-
- //[XmlRoot(ElementName = "Optional")]
- public class Optional
- {
- //[XmlElement(ElementName = "Attendee")]
- public List Attendee { get; set; }
- }
-
- //[XmlRoot(ElementName = "MeetingType")]
- public class MeetingType
- {
- //[XmlAttribute(AttributeName = "ID")]
- public string ID { get; set; }
- //[XmlAttribute(AttributeName = "Value")]
- public string Value { get; set; }
- }
-
- //[XmlRoot(ElementName = "MeetingTypes")]
- public class MeetingTypes
- {
- //[XmlElement(ElementName = "MeetingType")]
- public List MeetingType { get; set; }
- }
-
- //[XmlRoot(ElementName = "LiveMeeting")]
- public class LiveMeeting
- {
- //[XmlElement(ElementName = "URL")]
- public string URL { get; set; }
- //[XmlElement(ElementName = "ID")]
- public string ID { get; set; }
- //[XmlElement(ElementName = "Key")]
- public string Key { get; set; }
- //[XmlElement(ElementName = "Subject")]
- public string Subject { get; set; }
- }
-
- //[XmlRoot(ElementName = "LiveMeetingURL")]
- public class LiveMeetingURL
- {
- //[XmlElement(ElementName = "LiveMeeting")]
- public LiveMeeting LiveMeeting { get; set; }
- }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro.Fusion;
+
+using PepperDash.Core;
+
+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 FusionOccupancySensorAsset OccupancyAsset { get; set; }
+ public Dictionary StaticAssets { get; set; }
+
+ public FusionRoomGuids()
+ {
+ StaticAssets = new Dictionary();
+ OccupancyAsset = new FusionOccupancySensorAsset();
+ }
+
+ public FusionRoomGuids(string roomName, uint ipId, string roomGuid, Dictionary staticAssets)
+ {
+ RoomName = roomName;
+ IpId = ipId;
+ RoomGuid = roomGuid;
+
+ StaticAssets = staticAssets;
+ OccupancyAsset = new FusionOccupancySensorAsset();
+ }
+
+ public FusionRoomGuids(string roomName, uint ipId, string roomGuid, Dictionary staticAssets, FusionOccupancySensorAsset occAsset)
+ {
+ RoomName = roomName;
+ IpId = ipId;
+ RoomGuid = roomGuid;
+
+ StaticAssets = staticAssets;
+ OccupancyAsset = occAsset;
+ }
+
+ ///
+ /// Generates a new room GUID prefixed by the program slot number and NIC MAC address
+ ///
+ ///
+ ///
+ public string GenerateNewRoomGuid(uint progSlot, string mac)
+ {
+ Guid roomGuid = Guid.NewGuid();
+
+ return string.Format("{0}-{1}-{2}", progSlot, mac, roomGuid.ToString());
+ }
+
+
+ ///
+ /// Adds an asset to the StaticAssets collection and returns the new asset
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public FusionAsset AddStaticAsset(FusionRoom room, int uid, string assetName, string type, string instanceId)
+ {
+ var slotNum = GetNextAvailableAssetNumber(room);
+
+ Debug.Console(2, "Adding Fusion Asset: {0} of Type: {1} at Slot Number: {2} with GUID: {3}", assetName, type, slotNum, instanceId);
+
+ var tempAsset = new FusionAsset(slotNum, assetName, type, instanceId);
+
+ StaticAssets.Add(uid, tempAsset);
+
+ return tempAsset;
+ }
+
+ ///
+ /// Returns the next available slot number in the Fusion UserConfigurableAssetDetails collection
+ ///
+ ///
+ ///
+ public static uint GetNextAvailableAssetNumber(FusionRoom room)
+ {
+ uint slotNum = 0;
+
+ foreach (var item in room.UserConfigurableAssetDetails)
+ {
+ if(item.Number > slotNum)
+ slotNum = item.Number;
+ }
+
+ if (slotNum < 5)
+ {
+ slotNum = 5;
+ }
+ else
+ slotNum = slotNum + 1;
+
+ Debug.Console(2, "#Next available fusion asset number is: {0}", slotNum);
+
+ return slotNum;
+ }
+
+ }
+
+ public class FusionOccupancySensorAsset
+ {
+ // SlotNumber fixed at 4
+
+ public uint SlotNumber { get { return 4; } }
+ public string Name { get { return "Occupancy Sensor"; } }
+ public eAssetType Type { get; set; }
+ public string InstanceId { get; set; }
+
+ public FusionOccupancySensorAsset()
+ {
+ }
+
+ public FusionOccupancySensorAsset(eAssetType type)
+ {
+ Type = type;
+
+ InstanceId = Guid.NewGuid().ToString();
+ }
+ }
+
+ public class FusionAsset
+ {
+ public uint SlotNumber { get; set; }
+ public string Name { get; set; }
+ public string Type { get; set; }
+ public string InstanceId { get;set; }
+
+ public FusionAsset()
+ {
+
+ }
+
+ public FusionAsset(uint slotNum, string assetName, string type, string instanceId)
+ {
+ SlotNumber = slotNum;
+ Name = assetName;
+ Type = type;
+ if (string.IsNullOrEmpty(instanceId))
+ {
+ InstanceId = Guid.NewGuid().ToString();
+ }
+ else
+ {
+ InstanceId = instanceId;
+ }
+ }
+ }
+
+ //***************************************************************************************************
+
+ public class RoomSchedule
+ {
+ public List Meetings { get; set; }
+
+ public RoomSchedule()
+ {
+ Meetings = new List();
+ }
+ }
+
+ //****************************************************************************************************
+ // Helper Classes for XML API
+
+ ///
+ /// Data needed to request the local time from the Fusion server
+ ///
+ public class LocalTimeRequest
+ {
+ public string RequestID { get; set; }
+ }
+
+ ///
+ /// All the data needed for a full schedule request in a room
+ ///
+ /// //[XmlRoot(ElementName = "RequestSchedule")]
+ public class RequestSchedule
+ {
+ //[XmlElement(ElementName = "RequestID")]
+ public string RequestID { get; set; }
+ //[XmlElement(ElementName = "RoomID")]
+ public string RoomID { get; set; }
+ //[XmlElement(ElementName = "Start")]
+ public DateTime Start { get; set; }
+ //[XmlElement(ElementName = "HourSpan")]
+ public double HourSpan { get; set; }
+
+ public RequestSchedule(string requestID, string roomID)
+ {
+ RequestID = requestID;
+ RoomID = roomID;
+ Start = DateTime.Now;
+ HourSpan = 24;
+ }
+ }
+
+
+ //[XmlRoot(ElementName = "RequestAction")]
+ public class RequestAction
+ {
+ //[XmlElement(ElementName = "RequestID")]
+ public string RequestID { get; set; }
+ //[XmlElement(ElementName = "RoomID")]
+ public string RoomID { get; set; }
+ //[XmlElement(ElementName = "ActionID")]
+ public string ActionID { get; set; }
+ //[XmlElement(ElementName = "Parameters")]
+ public List Parameters { get; set; }
+
+ public RequestAction(string roomID, string actionID, List parameters)
+ {
+ RoomID = roomID;
+ ActionID = actionID;
+ Parameters = parameters;
+ }
+ }
+
+ //[XmlRoot(ElementName = "ActionResponse")]
+ public class ActionResponse
+ {
+ //[XmlElement(ElementName = "RequestID")]
+ public string RequestID { get; set; }
+ //[XmlElement(ElementName = "ActionID")]
+ public string ActionID { get; set; }
+ //[XmlElement(ElementName = "Parameters")]
+ public List Parameters { get; set; }
+ }
+
+ //[XmlRoot(ElementName = "Parameter")]
+ public class Parameter
+ {
+ //[XmlAttribute(AttributeName = "ID")]
+ public string ID { get; set; }
+ //[XmlAttribute(AttributeName = "Value")]
+ public string Value { get; set; }
+ }
+
+ ////[XmlRoot(ElementName = "Parameters")]
+ //public class Parameters
+ //{
+ // //[XmlElement(ElementName = "Parameter")]
+ // public List Parameter { get; set; }
+ //}
+
+ ///
+ /// Data structure for a ScheduleResponse from Fusion
+ ///
+ /// //[XmlRoot(ElementName = "ScheduleResponse")]
+ public class ScheduleResponse
+ {
+ //[XmlElement(ElementName = "RequestID")]
+ public string RequestID { get; set; }
+ //[XmlElement(ElementName = "RoomID")]
+ public string RoomID { get; set; }
+ //[XmlElement(ElementName = "RoomName")]
+ public string RoomName { get; set; }
+ //[XmlElement("Event")]
+ public List Events { get; set; }
+
+ public ScheduleResponse()
+ {
+ Events = new List();
+ }
+ }
+
+ //[XmlRoot(ElementName = "Event")]
+ public class Event
+ {
+ //[XmlElement(ElementName = "MeetingID")]
+ public string MeetingID { get; set; }
+ //[XmlElement(ElementName = "RVMeetingID")]
+ public string RVMeetingID { get; set; }
+ //[XmlElement(ElementName = "Recurring")]
+ public string Recurring { get; set; }
+ //[XmlElement(ElementName = "InstanceID")]
+ public string InstanceID { get; set; }
+ //[XmlElement(ElementName = "dtStart")]
+ public DateTime dtStart { get; set; }
+ //[XmlElement(ElementName = "dtEnd")]
+ public DateTime dtEnd { get; set; }
+ //[XmlElement(ElementName = "Organizer")]
+ public string Organizer { get; set; }
+ //[XmlElement(ElementName = "Attendees")]
+ public Attendees Attendees { get; set; }
+ //[XmlElement(ElementName = "Resources")]
+ public Resources Resources { get; set; }
+ //[XmlElement(ElementName = "IsEvent")]
+ public string IsEvent { get; set; }
+ //[XmlElement(ElementName = "IsRoomViewMeeting")]
+ public string IsRoomViewMeeting { get; set; }
+ //[XmlElement(ElementName = "IsPrivate")]
+ public string IsPrivate { get; set; }
+ //[XmlElement(ElementName = "IsExchangePrivate")]
+ public string IsExchangePrivate { get; set; }
+ //[XmlElement(ElementName = "MeetingTypes")]
+ public MeetingTypes MeetingTypes { get; set; }
+ //[XmlElement(ElementName = "ParticipantCode")]
+ public string ParticipantCode { get; set; }
+ //[XmlElement(ElementName = "PhoneNo")]
+ public string PhoneNo { get; set; }
+ //[XmlElement(ElementName = "WelcomeMsg")]
+ public string WelcomeMsg { get; set; }
+ //[XmlElement(ElementName = "Subject")]
+ public string Subject { get; set; }
+ //[XmlElement(ElementName = "LiveMeeting")]
+ public LiveMeeting LiveMeeting { get; set; }
+ //[XmlElement(ElementName = "ShareDocPath")]
+ public string ShareDocPath { get; set; }
+ //[XmlElement(ElementName = "HaveAttendees")]
+ public string HaveAttendees { get; set; }
+ //[XmlElement(ElementName = "HaveResources")]
+ public string HaveResources { get; set; }
+
+ ///
+ /// Gets the duration of the meeting
+ ///
+ public string DurationInMinutes
+ {
+ get
+ {
+ string duration;
+
+ var timeSpan = dtEnd.Subtract(dtStart);
+ int hours = timeSpan.Hours;
+ double minutes = timeSpan.Minutes;
+ double roundedMinutes = Math.Round(minutes);
+ if (hours > 0)
+ {
+ duration = string.Format("{0} hours {1} minutes", hours, roundedMinutes);
+ }
+ else
+ {
+ duration = string.Format("{0} minutes", roundedMinutes);
+ }
+
+ return duration;
+ }
+ }
+
+ ///
+ /// Gets the remaining time in the meeting. Returns null if the meeting is not currently in progress.
+ ///
+ public string RemainingTime
+ {
+ get
+ {
+ var now = DateTime.Now;
+
+ string remainingTime;
+
+ if (GetInProgress())
+ {
+ var timeSpan = dtEnd.Subtract(now);
+ int hours = timeSpan.Hours;
+ double minutes = timeSpan.Minutes;
+ double roundedMinutes = Math.Round(minutes);
+ if (hours > 0)
+ {
+ remainingTime = string.Format("{0} hours {1} minutes", hours, roundedMinutes);
+ }
+ else
+ {
+ remainingTime = string.Format("{0} minutes", roundedMinutes);
+ }
+
+ return remainingTime;
+ }
+ else
+ return null;
+ }
+
+ }
+
+ ///
+ /// Indicates that the meeting is in progress
+ ///
+ public bool isInProgress
+ {
+ get
+ {
+ return GetInProgress();
+ }
+ }
+
+ ///
+ /// Determines if the meeting is in progress
+ ///
+ /// Returns true if in progress
+ bool GetInProgress()
+ {
+ var now = DateTime.Now;
+
+ if (now > dtStart && now < dtEnd)
+ {
+ return true;
+ }
+ else
+ return false;
+ }
+ }
+
+ //[XmlRoot(ElementName = "Resources")]
+ public class Resources
+ {
+ //[XmlElement(ElementName = "Rooms")]
+ public Rooms Rooms { get; set; }
+ }
+
+ //[XmlRoot(ElementName = "Rooms")]
+ public class Rooms
+ {
+ //[XmlElement(ElementName = "Room")]
+ public List Room { get; set; }
+ }
+
+ //[XmlRoot(ElementName = "Room")]
+ public class Room
+ {
+ //[XmlElement(ElementName = "Name")]
+ public string Name { get; set; }
+ //[XmlElement(ElementName = "ID")]
+ public string ID { get; set; }
+ //[XmlElement(ElementName = "MPType")]
+ public string MPType { get; set; }
+ }
+
+ //[XmlRoot(ElementName = "Attendees")]
+ public class Attendees
+ {
+ //[XmlElement(ElementName = "Required")]
+ public Required Required { get; set; }
+ //[XmlElement(ElementName = "Optional")]
+ public Optional Optional { get; set; }
+ }
+
+ //[XmlRoot(ElementName = "Required")]
+ public class Required
+ {
+ //[XmlElement(ElementName = "Attendee")]
+ public List Attendee { get; set; }
+ }
+
+ //[XmlRoot(ElementName = "Optional")]
+ public class Optional
+ {
+ //[XmlElement(ElementName = "Attendee")]
+ public List Attendee { get; set; }
+ }
+
+ //[XmlRoot(ElementName = "MeetingType")]
+ public class MeetingType
+ {
+ //[XmlAttribute(AttributeName = "ID")]
+ public string ID { get; set; }
+ //[XmlAttribute(AttributeName = "Value")]
+ public string Value { get; set; }
+ }
+
+ //[XmlRoot(ElementName = "MeetingTypes")]
+ public class MeetingTypes
+ {
+ //[XmlElement(ElementName = "MeetingType")]
+ public List MeetingType { get; set; }
+ }
+
+ //[XmlRoot(ElementName = "LiveMeeting")]
+ public class LiveMeeting
+ {
+ //[XmlElement(ElementName = "URL")]
+ public string URL { get; set; }
+ //[XmlElement(ElementName = "ID")]
+ public string ID { get; set; }
+ //[XmlElement(ElementName = "Key")]
+ public string Key { get; set; }
+ //[XmlElement(ElementName = "Subject")]
+ public string Subject { get; set; }
+ }
+
+ //[XmlRoot(ElementName = "LiveMeetingURL")]
+ public class LiveMeetingURL
+ {
+ //[XmlElement(ElementName = "LiveMeeting")]
+ public LiveMeeting LiveMeeting { get; set; }
+ }
}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs b/Essentials/PepperDashEssentials/OTHER/Fusion/FusionSystemController.cs
similarity index 97%
rename from Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs
rename to Essentials/PepperDashEssentials/OTHER/Fusion/FusionSystemController.cs
index f2568b8c..59b53112 100644
--- a/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs
+++ b/Essentials/PepperDashEssentials/OTHER/Fusion/FusionSystemController.cs
@@ -1,1394 +1,1394 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using Crestron.SimplSharp;
-using Crestron.SimplSharp.CrestronIO;
-using Crestron.SimplSharp.CrestronXml;
-using Crestron.SimplSharp.CrestronXml.Serialization;
-using Crestron.SimplSharp.CrestronXmlLinq;
-using Crestron.SimplSharpPro;
-using Crestron.SimplSharpPro.DeviceSupport;
-using Crestron.SimplSharpPro.Fusion;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-
-using PepperDash.Core;
-using PepperDash.Essentials;
-using PepperDash.Essentials.Core;
-using PepperDash.Essentials.Devices.Common;
-
-
-
-namespace PepperDash.Essentials.Fusion
-{
- public class EssentialsHuddleSpaceFusionSystemController : Device
- {
- public event EventHandler ScheduleChange;
- public event EventHandler MeetingEndWarning;
- public event EventHandler NextMeetingBeginWarning;
-
- FusionRoom FusionRoom;
- EssentialsHuddleSpaceRoom Room;
- Dictionary SourceToFeedbackSigs =
- new Dictionary();
-
- //BooleanSigData OccupancyStatusSig;
-
- StatusMonitorCollection ErrorMessageRollUp;
-
- StringSigData CurrentRoomSourceNameSig;
-
- #region System Info Sigs
- //StringSigData SystemName;
- //StringSigData Model;
- //StringSigData SerialNumber;
- //StringSigData Uptime;
- #endregion
-
-
- #region Processor Info Sigs
- StringSigData Ip1;
- StringSigData Ip2;
- StringSigData Gateway;
- StringSigData Hostname;
- StringSigData Domain;
- StringSigData Dns1;
- StringSigData Dns2;
- StringSigData Mac1;
- StringSigData Mac2;
- StringSigData NetMask1;
- StringSigData NetMask2;
- StringSigData Firmware;
-
- StringSigData[] Program = new StringSigData[10];
- #endregion
-
- #region Default Display Source Sigs
-
- BooleanSigData[] Source = new BooleanSigData[10];
-
- #endregion
-
- RoomSchedule CurrentSchedule;
-
- Event NextMeeting;
-
- Event CurrentMeeting;
-
- string RoomGuid
- {
- get
- {
- return GUIDs.RoomGuid;
- }
-
- }
-
- uint IpId;
-
- FusionRoomGuids GUIDs;
-
- bool GuidFileExists;
-
- bool IsRegisteredForSchedulePushNotifications = false;
-
- CTimer PollTimer = null;
-
- CTimer PushNotificationTimer = null;
-
- // Default poll time is 5 min unless overridden by config value
- public long SchedulePollInterval = 300000;
-
- public long PushNotificationTimeout = 5000;
-
- Dictionary FusionStaticAssets;
-
- FusionOccupancySensorAsset FusionOccSensor;
-
- //ScheduleResponseEvent NextMeeting;
-
- public EssentialsHuddleSpaceFusionSystemController(EssentialsHuddleSpaceRoom room, uint ipId)
- : base(room.Key + "-fusion")
- {
-
- Room = room;
-
- IpId = ipId;
-
- FusionStaticAssets = new Dictionary();
-
- GUIDs = new FusionRoomGuids();
-
- var mac = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0);
-
- var slot = Global.ControlSystem.ProgramNumber;
-
- string guidFilePath = string.Format(@"\NVRAM\Program{0}\{1}-FusionGuids.json", Global.ControlSystem.ProgramNumber, InitialParametersClass.ProgramIDTag);
-
- GuidFileExists = File.Exists(guidFilePath);
-
- if (GuidFileExists)
- {
- ReadGuidFile(guidFilePath);
- }
- else
- {
- GUIDs = new FusionRoomGuids(Room.Name, ipId, GUIDs.GenerateNewRoomGuid(slot, mac), FusionStaticAssets);
- }
-
- CreateSymbolAndBasicSigs(IpId);
- SetUpSources();
- SetUpCommunitcationMonitors();
- SetUpDisplay();
- SetUpError();
- //SetUpOccupancy();
-
- // Make it so!
- FusionRVI.GenerateFileForAllFusionDevices();
-
- GenerateGuidFile(guidFilePath);
- }
-
- ///
- /// Generates the guid file in NVRAM. If the file already exists it will be overwritten.
- ///
- /// 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");
-
- if (FusionOccSensor == null)
- GUIDs = new FusionRoomGuids(Room.Name, IpId, RoomGuid, FusionStaticAssets);
- else
- GUIDs = new FusionRoomGuids(Room.Name, IpId, RoomGuid, FusionStaticAssets, FusionOccSensor);
-
- 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);
-
- GUIDs = JsonConvert.DeserializeObject(JSON);
-
- IpId = GUIDs.IpId;
-
- FusionStaticAssets = GUIDs.StaticAssets;
-
- }
-
- Debug.Console(0, this, "Fusion Guids successfully read from file:");
-
- Debug.Console(1, this, "\nRoom Name: {0}\nIPID: {1:x}\n RoomGuid: {2}", Room.Name, IpId, RoomGuid);
-
- foreach (KeyValuePair item in FusionStaticAssets)
- {
- Debug.Console(1, this, "\nAsset Name: {0}\nAsset No: {1}\n Guid: {2}", item.Value.Name, item.Value.SlotNumber, item.Value.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}", RoomGuid);
-
- FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
- FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();
- FusionRoom.ExtenderFusionRoomDataReservedSigs.Use();
-
- FusionRoom.Register();
-
- 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);
- CrestronConsole.AddNewConsoleCommand(CreateAsHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
-
- // Room to fusion room
- Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
-
- // Moved to
- CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(84, "Display 1 - Current Source", eSigIoMask.InputSigOnly);
- // Don't think we need to get current status of this as nothing should be alive yet.
- Room.CurrentSingleSourceChange += new SourceInfoChangeHandler(Room_CurrentSourceInfoChange);
-
-
- FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction(Room.PowerOnToDefaultOrLastSource);
- FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => Room.RunRouteAction("roomOff"));
- // NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig);
- 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;";
-
- GetProcessorEthernetValues();
-
- GetSystemInfo();
-
- GetProcessorInfo();
-
- CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
- }
-
- void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs)
- {
- if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp)
- {
- GetProcessorEthernetValues();
- }
- }
-
- void GetSystemInfo()
- {
- //SystemName.InputSig.StringValue = Room.Name;
- //Model.InputSig.StringValue = InitialParametersClass.ControllerPromptName;
- //SerialNumber.InputSig.StringValue = InitialParametersClass.
-
- string response = string.Empty;
-
- var systemReboot = FusionRoom.CreateOffsetBoolSig(74, "Processor - Reboot", eSigIoMask.OutputSigOnly);
- systemReboot.OutputSig.SetSigFalseAction(() => CrestronConsole.SendControlSystemCommand("reboot", ref response));
- }
-
- void GetProcessorEthernetValues()
- {
- Ip1 = FusionRoom.CreateOffsetStringSig(50, "Info - Processor - IP 1", eSigIoMask.InputSigOnly);
- Ip2 = FusionRoom.CreateOffsetStringSig(51, "Info - Processor - IP 2", eSigIoMask.InputSigOnly);
- Gateway = FusionRoom.CreateOffsetStringSig(52, "Info - Processor - Gateway", eSigIoMask.InputSigOnly);
- Hostname = FusionRoom.CreateOffsetStringSig(53, "Info - Processor - Hostname", eSigIoMask.InputSigOnly);
- Domain = FusionRoom.CreateOffsetStringSig(54, "Info - Processor - Domain", eSigIoMask.InputSigOnly);
- Dns1 = FusionRoom.CreateOffsetStringSig(55, "Info - Processor - DNS 1", eSigIoMask.InputSigOnly);
- Dns2 = FusionRoom.CreateOffsetStringSig(56, "Info - Processor - DNS 2", eSigIoMask.InputSigOnly);
- Mac1 = FusionRoom.CreateOffsetStringSig(57, "Info - Processor - MAC 1", eSigIoMask.InputSigOnly);
- Mac2 = FusionRoom.CreateOffsetStringSig(58, "Info - Processor - MAC 2", eSigIoMask.InputSigOnly);
- NetMask1 = FusionRoom.CreateOffsetStringSig(59, "Info - Processor - Net Mask 1", eSigIoMask.InputSigOnly);
- NetMask2 = FusionRoom.CreateOffsetStringSig(60, "Info - Processor - Net Mask 2", eSigIoMask.InputSigOnly);
-
- // Interface =0
- Ip1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0);
- Gateway.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, 0);
- Hostname.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0);
- Domain.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, 0);
-
- var dnsServers = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DNS_SERVER, 0).Split(',');
- Dns1.InputSig.StringValue = dnsServers[0];
- if (dnsServers.Length > 1)
- Dns2.InputSig.StringValue = dnsServers[1];
-
- Mac1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0);
- NetMask1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, 0);
-
- // Interface 1
-
- if (InitialParametersClass.NumberOfEthernetInterfaces > 1) // Only get these values if the processor has more than 1 NIC
- {
- Ip2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 1);
- Mac2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 1);
- NetMask2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, 1);
- }
- }
-
- void GetProcessorInfo()
- {
- //SystemName = FusionRoom.CreateOffsetStringSig(50, "Info - Processor - System Name", eSigIoMask.InputSigOnly);
- //Model = FusionRoom.CreateOffsetStringSig(51, "Info - Processor - Model", eSigIoMask.InputSigOnly);
- //SerialNumber = FusionRoom.CreateOffsetStringSig(52, "Info - Processor - Serial Number", eSigIoMask.InputSigOnly);
- //Uptime = FusionRoom.CreateOffsetStringSig(53, "Info - Processor - Uptime", eSigIoMask.InputSigOnly);
-
- Firmware = FusionRoom.CreateOffsetStringSig(61, "Info - Processor - Firmware", eSigIoMask.InputSigOnly);
-
- for (int i = 0; i < Global.ControlSystem.NumProgramsSupported; i++)
- {
- var join = 62 + i;
- var progNum = i + 1;
- Program[i] = FusionRoom.CreateOffsetStringSig((uint)join, string.Format("Info - Processor - Program {0}", progNum), eSigIoMask.InputSigOnly);
- }
-
- Firmware.InputSig.StringValue = InitialParametersClass.FirmwareVersion;
-
- //var programs = ProcessorProgReg.GetProcessorProgReg();
-
- //for (int i = 1; i < Global.ControlSystem.NumProgramsSupported; i++)
- //{
- // var join = 62 + i;
- // var progNum = i + 1;
- // if (programs[i].Exists)
- // Program[i].InputSig.StringValue = programs[i].Name;
- //}
-
- }
-
- void GetTouchpanelInfo()
- {
- // TODO Get IP and Project Name from TP
- }
-
- void FusionRoom_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
- {
- if (args.DeviceOnLine)
- {
- CrestronEnvironment.Sleep(200);
-
- // Send Push Notification Action request:
-
- string requestID = "InitialPushRequest";
-
-
- string actionRequest =
- string.Format("\n{0}\n", requestID) +
- "RegisterPushModel\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n";
-
- Debug.Console(2, this, "Sending Fusion ActionRequest: \n{0}", actionRequest);
-
- FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = actionRequest;
-
-
- // Request current Fusion Server Time
-
- string timeRequestID = "TimeRequest";
-
- string timeRequest = string.Format("{0}", timeRequestID);
-
- FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQuery.StringValue = timeRequest;
- }
-
- }
-
- ///
- /// 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(object callbackObject)
- {
- DateTime now = DateTime.Today;
-
- string currentTime = now.ToString("s");
-
- string requestTest =
- string.Format("FullSchedleRequest{0}{1}24", RoomGuid, currentTime);
-
- Debug.Console(2, this, "Sending Fusion ScheduleQuery: \n{0}", requestTest);
-
- FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleQuery.StringValue = requestTest;
-
- if (IsRegisteredForSchedulePushNotifications)
- PushNotificationTimer.Stop();
- }
-
- ///
- /// Wrapper method to allow console commands to modify the current meeting end time
- ///
- /// meetingID extendTime
- public void ModifyMeetingEndTimeConsoleHelper(string command)
- {
- string requestID;
- string meetingID = null;
- int extendMinutes = -1;
-
- requestID = "ModifyMeetingTest12345";
-
- try
- {
- var tokens = command.Split(' ');
-
- meetingID = tokens[0];
- extendMinutes = Int32.Parse(tokens[1]);
-
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error parsing console command: {0}", e);
- }
-
- ModifyMeetingEndTime(requestID, extendMinutes);
-
- }
-
- ///
- /// Ends or Extends the current meeting by the specified number of minutes.
- ///
- /// Number of minutes to extend the meeting. A value of 0 will end the meeting.
- public void ModifyMeetingEndTime(string requestID, int extendMinutes)
- {
- if(CurrentMeeting == null)
- {
- Debug.Console(1, this, "No meeting in progress. Unable to modify end time.");
- return;
- }
-
- if (extendMinutes > -1)
- {
- if(extendMinutes > 0)
- {
- var extendTime = CurrentMeeting.dtEnd - DateTime.Now;
- double extendMinutesRaw = extendTime.TotalMinutes;
-
- extendMinutes = extendMinutes + (int)Math.Round(extendMinutesRaw);
- }
-
-
- string requestTest = string.Format(
- "{0}{1}MeetingChange"
- , requestID, RoomGuid, CurrentMeeting.MeetingID, extendMinutes);
-
- Debug.Console(1, this, "Sending MeetingChange Request: \n{0}", requestTest);
-
- FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = requestTest;
- }
- else
- {
- Debug.Console(1, this, "Invalid time specified");
- }
-
-
- }
-
- ///
- /// Creates and Ad Hoc meeting with a duration of 1 hour, or until the next meeting if in less than 1 hour.
- ///
- public void CreateAsHocMeeting(string command)
- {
- string requestID = "CreateAdHocMeeting";
-
- DateTime now = DateTime.Now.AddMinutes(1);
-
- now.AddSeconds(-now.Second);
-
- // Assume 1 hour meeting if possible
- DateTime dtEnd = now.AddHours(1);
-
- // Check if room is available for 1 hour before next meeting
- if (NextMeeting != null)
- {
- var roomAvailable = NextMeeting.dtEnd.Subtract(dtEnd);
-
- if (roomAvailable.TotalMinutes < 60)
- {
- /// Room not available for full hour, book until next meeting starts
- dtEnd = NextMeeting.dtEnd;
- }
- }
-
- string createMeetingRequest =
- "" +
- string.Format("{0}", requestID) +
- string.Format("{0}", RoomGuid) +
- "" +
- string.Format("{0}", now.ToString("s")) +
- string.Format("{0}", dtEnd.ToString("s")) +
- "AdHoc Meeting" +
- "Room User" +
- "Example Message" +
- "" +
- "";
-
- Debug.Console(2, this, "Sending CreateMeeting Request: \n{0}", createMeetingRequest);
-
- FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateMeeting.StringValue = createMeetingRequest;
-
- //Debug.Console(1, this, "Sending CreateMeeting Request: \n{0}", command);
-
- //FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateMeeting.StringValue = command;
-
- }
-
- ///
- /// Event handler method for Device Extender sig changes
- ///
- ///
- ///
- void ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
- {
- Debug.Console(2, this, "Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue);
-
-
- if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQueryResponse)
- {
- try
- {
- XmlDocument message = new XmlDocument();
-
- message.LoadXml(args.Sig.StringValue);
-
- var actionResponse = message["ActionResponse"];
-
- if (actionResponse != null)
- {
- var requestID = actionResponse["RequestID"];
-
- if (requestID.InnerText == "InitialPushRequest")
- {
- if (actionResponse["ActionID"].InnerText == "RegisterPushModel")
- {
- var parameters = actionResponse["Parameters"];
-
- foreach (XmlElement parameter in parameters)
- {
- if (parameter.HasAttributes)
- {
- var attributes = parameter.Attributes;
-
- if (attributes["ID"].Value == "Registered")
- {
- var isRegistered = Int32.Parse(attributes["Value"].Value);
-
- if (isRegistered == 1)
- {
- IsRegisteredForSchedulePushNotifications = true;
-
- if (PollTimer != null && !PollTimer.Disposed)
- {
- PollTimer.Stop();
- PollTimer.Dispose();
- }
-
- PushNotificationTimer = new CTimer(RequestFullRoomSchedule, null, PushNotificationTimeout, PushNotificationTimeout);
-
- PushNotificationTimer.Reset(PushNotificationTimeout, PushNotificationTimeout);
- }
- else if (isRegistered == 0)
- {
- IsRegisteredForSchedulePushNotifications = false;
-
- if (PushNotificationTimer != null && !PushNotificationTimer.Disposed)
- {
- PushNotificationTimer.Stop();
- PushNotificationTimer.Dispose();
- }
-
- PollTimer = new CTimer(RequestFullRoomSchedule, null, SchedulePollInterval, SchedulePollInterval);
-
- PollTimer.Reset(SchedulePollInterval, SchedulePollInterval);
- }
- }
- }
- }
- }
- }
- }
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error parsing ActionQueryResponse: {0}", e);
- }
- }
- else if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQueryResponse)
- {
- try
- {
- XmlDocument message = new XmlDocument();
-
- message.LoadXml(args.Sig.StringValue);
-
- var localDateTimeResponse = message["LocalTimeResponse"];
-
- if (localDateTimeResponse != null)
- {
- var localDateTime = localDateTimeResponse["LocalDateTime"];
-
- if (localDateTime != null)
- {
- var tempLocalDateTime = localDateTime.InnerText;
-
- DateTime currentTime = DateTime.Parse(tempLocalDateTime);
-
- Debug.Console(1, this, "DateTime from Fusion Server: {0}", currentTime);
-
- // Parse time and date from response and insert values
- CrestronEnvironment.SetTimeAndDate((ushort)currentTime.Hour, (ushort)currentTime.Minute, (ushort)currentTime.Second, (ushort)currentTime.Month, (ushort)currentTime.Day, (ushort)currentTime.Year);
-
- Debug.Console(1, this, "Processor time set to {0}", CrestronEnvironment.GetLocalTime());
- }
- }
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error parsing LocalDateTimeQueryResponse: {0}", e);
- }
- }
- }
-
- ///
- /// Event handler method for Device Extender sig changes
- ///
- ///
- ///
- void FusionRoomSchedule_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
- {
- Debug.Console(2, this, "Scehdule Response 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);
-
- var response = message["ScheduleResponse"];
-
- if (response != null)
- {
- // Check for push notification
- if (response["RequestID"].InnerText == "RVRequest")
- {
- var action = response["Action"];
-
- if (action.OuterXml.IndexOf("RequestSchedule") > -1)
- {
- PushNotificationTimer.Reset(PushNotificationTimeout, PushNotificationTimeout);
- }
- }
- else // Not a push notification
- {
- CurrentSchedule = new RoomSchedule(); // Clear Current Schedule
- CurrentMeeting = null; // Clear Current Meeting
- NextMeeting = null; // Clear Next Meeting
-
- bool isNextMeeting = false;
-
- 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(2, 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);
-
- // Check is this is the current event
- if (tempEvent.dtStart <= DateTime.Now && tempEvent.dtEnd >= DateTime.Now)
- {
- CurrentMeeting = tempEvent; // Set Current Meeting
- isNextMeeting = true; // Flag that next element is next meeting
- }
-
- if (isNextMeeting)
- {
- NextMeeting = tempEvent; // Set Next Meeting
- isNextMeeting = false;
- }
-
- CurrentSchedule.Meetings.Add(tempEvent);
- }
-
- }
-
- PrintTodaysSchedule();
-
- if (!IsRegisteredForSchedulePushNotifications)
- PollTimer.Reset(SchedulePollInterval, SchedulePollInterval);
-
- // Fire Schedule Change Event
- var handler = ScheduleChange;
-
- if (handler != null)
- {
- handler(this, new ScheduleChangeEventArgs() { Schedule = CurrentSchedule });
- }
-
- }
- }
-
-
-
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error parsing ScheduleResponse: {0}", e);
- }
- }
- else if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateResponse)
- {
- Debug.Console(2, this, "Create Meeting Response Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue);
- }
-
- }
-
- ///
- /// Prints today's schedule to console for debugging
- ///
- void PrintTodaysSchedule()
- {
- if (Debug.Level > 1)
- {
- if (CurrentSchedule.Meetings.Count > 0)
- {
- Debug.Console(1, this, "Today's Schedule for '{0}'\n", Room.Name);
-
- foreach (Event e in CurrentSchedule.Meetings)
- {
- Debug.Console(1, this, "Subject: {0}", e.Subject);
- Debug.Console(1, this, "Organizer: {0}", e.Organizer);
- Debug.Console(1, this, "MeetingID: {0}", e.MeetingID);
- Debug.Console(1, this, "Start Time: {0}", e.dtStart);
- Debug.Console(1, this, "End Time: {0}", e.dtEnd);
- Debug.Console(1, this, "Duration: {0}\n", e.DurationInMinutes);
- }
- }
- }
- }
-
- void SetUpSources()
- {
- // Sources
- var dict = ConfigReader.ConfigObject.GetSourceListForKey(Room.SourceListKey);
- if (dict != null)
- {
- // NEW PROCESS:
- // Make these lists and insert the fusion attributes by iterating these
- var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
- uint i = 1;
- foreach (var kvp in setTopBoxes)
- {
- TryAddRouteActionSigs("Display 1 - Source TV " + i, 188 + i, kvp.Key, kvp.Value.SourceDevice);
- i++;
- if (i > 5) // We only have five spots
- break;
- }
-
- var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
- i = 1;
- foreach (var kvp in discPlayers)
- {
- TryAddRouteActionSigs("Display 1 - Source DVD " + i, 181 + i, kvp.Key, kvp.Value.SourceDevice);
- i++;
- if (i > 5) // We only have five spots
- break;
- }
-
- var laptops = dict.Where(d => d.Value.SourceDevice is Laptop);
- i = 1;
- foreach (var kvp in laptops)
- {
- TryAddRouteActionSigs("Display 1 - Source Laptop " + i, 166 + i, kvp.Key, kvp.Value.SourceDevice);
- i++;
- if (i > 10) // We only have ten spots???
- break;
- }
-
- foreach (var kvp in dict)
- {
- var usageDevice = kvp.Value.SourceDevice as IUsageTracking;
-
- if (usageDevice != null)
- {
- usageDevice.UsageTracker = new UsageTracking(usageDevice as Device);
- usageDevice.UsageTracker.UsageIsTracked = true;
- usageDevice.UsageTracker.DeviceUsageEnded += new EventHandler(UsageTracker_DeviceUsageEnded);
- }
- }
-
- }
- else
- {
- Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'",
- Room.SourceListKey, Room.Key);
- }
- }
-
- ///
- /// Collects usage data from source and sends to Fusion
- ///
- ///
- ///
- void UsageTracker_DeviceUsageEnded(object sender, DeviceUsageEventArgs e)
- {
- var deviceTracker = sender as UsageTracking;
-
- var configDevice = ConfigReader.ConfigObject.Devices.Where(d => d.Key.Equals(deviceTracker.Parent));
-
- string group = ConfigReader.GetGroupForDeviceKey(deviceTracker.Parent.Key);
-
- string currentMeetingId = "-";
-
- if (CurrentMeeting != null)
- currentMeetingId = CurrentMeeting.MeetingID;
-
- //String Format: "USAGE||[Date YYYY-MM-DD]||[Time HH-mm-ss]||TIME||[Asset_Type]||[Asset_Name]||[Minutes_used]||[Asset_ID]||[Meeting_ID]"
- // [Asset_ID] property does not appear to be used in Crestron SSI examples. They are sending "-" instead so that's what is replicated here
- string deviceUsage = string.Format("USAGE||{0}||{1}||TIME||{2}||{3}||-||{4}||-||{5}||{6}||\r\n", e.UsageEndTime.ToString("yyyy-MM-dd"), e.UsageEndTime.ToString("HH:mm:ss"),
- group, deviceTracker.Parent.Name, e.MinutesUsed, "-", currentMeetingId);
-
- Debug.Console(1, this, "Device usage for: {0} ended at {1}. In use for {2} minutes", deviceTracker.Parent.Name, e.UsageEndTime, e.MinutesUsed);
-
- FusionRoom.DeviceUsage.InputSig.StringValue = deviceUsage;
-
- Debug.Console(1, this, "Device usage string: {0}", deviceUsage);
- }
-
-
- void TryAddRouteActionSigs(string attrName, uint attrNum, string routeKey, Device pSrc)
- {
- Debug.Console(2, this, "Creating attribute '{0}' with join {1} for source {2}",
- attrName, attrNum, pSrc.Key);
- try
- {
- var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputOutputSig);
- // Need feedback when this source is selected
- // Event handler, added below, will compare source changes with this sig dict
- SourceToFeedbackSigs.Add(pSrc, sigD.InputSig);
-
- // And respond to selection in Fusion
- sigD.OutputSig.SetSigFalseAction(() => Room.RunRouteAction(routeKey));
- }
- catch (Exception)
- {
- Debug.Console(2, this, "Error creating Fusion signal {0} {1} for device '{2}'. THIS NEEDS REWORKING", attrNum, attrName, pSrc.Key);
- }
- }
-
- ///
- ///
- ///
- void SetUpCommunitcationMonitors()
- {
- // Attach to all room's devices with monitors.
- //foreach (var dev in DeviceManager.Devices)
- foreach (var dev in DeviceManager.GetDevices())
- {
- if (!(dev is ICommunicationMonitor))
- continue;
-
- var keyNum = ExtractNumberFromKey(dev.Key);
- if (keyNum == -1)
- {
- Debug.Console(1, this, "WARNING: Cannot link device '{0}' to numbered Fusion monitoring attributes",
- dev.Key);
- continue;
- }
- string attrName = null;
- uint attrNum = Convert.ToUInt32(keyNum);
-
- if (dev is EssentialsTouchpanelController)
- {
- if ((dev as EssentialsTouchpanelController).Panel is Crestron.SimplSharpPro.DeviceSupport.TswFt5Button)
- {
- if (attrNum > 10)
- continue;
- attrName = "Online - Touch Panel " + attrNum;
- attrNum += 150;
- }
- else if ((dev as EssentialsTouchpanelController).Panel is Crestron.SimplSharpPro.UI.XpanelForSmartGraphics)
- {
- if (attrNum > 10)
- continue;
- attrName = "Online - XPanel " + attrNum;
- attrNum += 160;
- }
- }
-
- //else
- if (dev is DisplayBase)
- {
- if (attrNum > 10)
- continue;
- attrName = "Online - Display " + attrNum;
- attrNum += 170;
- }
- //else if (dev is DvdDeviceBase)
- //{
- // if (attrNum > 5)
- // continue;
- // attrName = "Device Ok - DVD " + attrNum;
- // attrNum += 260;
- //}
- // add set top box
-
- // add Cresnet roll-up
-
- // add DM-devices roll-up
-
- if (attrName != null)
- {
- // Link comm status to sig and update
- var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputSigOnly);
- var smd = dev as ICommunicationMonitor;
- sigD.InputSig.BoolValue = smd.CommunicationMonitor.Status == MonitorStatus.IsOk;
- smd.CommunicationMonitor.StatusChange += (o, a) =>
- { sigD.InputSig.BoolValue = a.Status == MonitorStatus.IsOk; };
- Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", dev.Key, attrName);
- }
- }
- }
-
- void SetUpDisplay()
- {
- try
- {
- //Setup Display Usage Monitoring
-
- var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
-
- // Consider updating this in multiple display systems
-
- foreach (DisplayBase display in displays)
- {
- display.UsageTracker = new UsageTracking(display);
- display.UsageTracker.UsageIsTracked = true;
- display.UsageTracker.DeviceUsageEnded += new EventHandler(UsageTracker_DeviceUsageEnded);
- }
-
- var defaultDisplay = Room.DefaultDisplay as DisplayBase;
- if (defaultDisplay == null)
- {
- Debug.Console(1, this, "Cannot link null display to Fusion");
- return;
- }
-
- var dispPowerOnAction = new Action(b => { if (!b) defaultDisplay.PowerOn(); });
- var dispPowerOffAction = new Action(b => { if (!b) defaultDisplay.PowerOff(); });
-
- // Display to fusion room sigs
- FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
- FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
- defaultDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
- if (defaultDisplay is IDisplayUsage)
- (defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
-
-
-
- MapDisplayToRoomJoins(1, 158, defaultDisplay);
-
-
- var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
-
- //Check for existing asset in GUIDs collection
-
- var tempAsset = new FusionAsset();
-
- if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
- {
- tempAsset = FusionStaticAssets[deviceConfig.Uid];
- }
- else
- {
- // Create a new asset
- tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), defaultDisplay.Name, "Display", "");
- FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
- }
-
- var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
- dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
- dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
- defaultDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
- // NO!! display.PowerIsOn.LinkComplementInputSig(dispAsset.PowerOff.InputSig);
- // Use extension methods
- dispAsset.TrySetMakeModel(defaultDisplay);
- dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error setting up display in Fusion: {0}", e);
- }
-
- }
-
- ///
- /// Maps room attributes to a display at a specified index
- ///
- ///
- /// a
- void MapDisplayToRoomJoins(int displayIndex, int joinOffset, DisplayBase display)
- {
- string displayName = string.Format("Display {0} - ", displayIndex);
-
-
- if(display == Room.DefaultDisplay)
- {
- // Display volume
- var defaultDisplayVolume = FusionRoom.CreateOffsetUshortSig(50, "Volume - Fader01", eSigIoMask.InputOutputSig);
- defaultDisplayVolume.OutputSig.UserObject = new Action(b => (display as IBasicVolumeWithFeedback).SetVolume(b));
- (display as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(defaultDisplayVolume.InputSig);
-
- // Power on
- var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
- defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOn(); });
- display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
-
- // Power Off
- var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
- defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOff(); }); ;
- display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
-
- // Current Source
- var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
- defaultDisplaySourceNone.OutputSig.UserObject = new Action(b => { if (!b) Room.RunRouteAction("roomOff"); }); ;
-
- //var dict = ConfigReader.ConfigObject.GetSourceListForKey(Room.SourceListKey);
-
- //foreach (var item in dict)
- //{
- // if(item.Key != "roomOff")
- // {
- // var defaultDisplaySource = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + (uint)item.Value.Order + 9 , string.Format("{0}Source {1}", displayIndex, item.Value.Order), eSigIoMask.InputOutputSig);
- // defaultDisplaySource.OutputSig.UserObject = new Action(b => { if (!b) Room.RunRouteAction(item.Key); });
-
- // //defaultDisplaySource.InputSig = Source[item.Value.Order].InputSig;
- // }
-
- //}
- }
- }
-
- //void Room_CurrentSingleSourceChange(EssentialsRoomBase room, SourceListItem info, ChangeType type)
- //{
- // for (int i = 1; i <= Source.Length; i++)
- // {
- // Source[i].InputSig.BoolValue = false;
- // }
-
- // Source[info.Order].InputSig.BoolValue = true;
-
- // // Need to check for current source key against source list and update Source[] BooleanSigData as appropriate
-
- //}
-
- void SetUpError()
- {
- // Roll up ALL device errors
- ErrorMessageRollUp = new StatusMonitorCollection(this);
- foreach (var dev in DeviceManager.GetDevices())
- {
- var md = dev as ICommunicationMonitor;
- if (md != null)
- {
- ErrorMessageRollUp.AddMonitor(md.CommunicationMonitor);
- Debug.Console(2, this, "Adding '{0}' to room's overall error monitor", md.CommunicationMonitor.Parent.Key);
- }
- }
- ErrorMessageRollUp.Start();
- FusionRoom.ErrorMessage.InputSig.StringValue = ErrorMessageRollUp.Message;
- ErrorMessageRollUp.StatusChange += (o, a) =>
- {
- FusionRoom.ErrorMessage.InputSig.StringValue = ErrorMessageRollUp.Message;
- };
-
- }
-
- void SetUpOccupancy()
- {
-
- // Need to have the room occupancy object first and somehow determine the slot number of the Occupancy asset but will not be able to use the UID from config likely.
- // Consider defining an object just for Room Occupancy (either eAssetType.Occupancy Sensor (local) or eAssetType.RemoteOccupancySensor (from Fusion sched. panel)) and reserving slot 4 for that asset (statics would start at 5)
-
- //if (Room.OccupancyObj != null)
- //{
-
- var tempOccAsset = GUIDs.OccupancyAsset;
-
- if(tempOccAsset == null)
- {
- FusionOccSensor = new FusionOccupancySensorAsset(eAssetType.OccupancySensor);
- tempOccAsset = FusionOccSensor;
- }
-
- var occSensorAsset = FusionRoom.CreateOccupancySensorAsset(tempOccAsset.SlotNumber, tempOccAsset.Name, "Occupancy Sensor", tempOccAsset.InstanceId);
-
- occSensorAsset.RoomOccupied.AddSigToRVIFile = true;
-
- var occSensorShutdownMinutes = FusionRoom.CreateOffsetUshortSig(70, "Occ Shutdown - Minutes", eSigIoMask.InputOutputSig);
-
- // Tie to method on occupancy object
- //occSensorShutdownMinutes.OutputSig.UserObject(new Action(ushort)(b => Room.OccupancyObj.SetShutdownMinutes(b));
-
-
- // use Room.OccObject.RoomOccupiedFeedback.LinkInputSig(occSensorAsset.InputSig);
- //}
- }
-
- ///
- /// Helper to get the number from the end of a device's key string
- ///
- /// -1 if no number matched
- int ExtractNumberFromKey(string key)
- {
- var capture = System.Text.RegularExpressions.Regex.Match(key, @"\D+(\d+)");
- if (!capture.Success)
- return -1;
- else return Convert.ToInt32(capture.Groups[1].Value);
- }
-
- ///
- /// Event handler for when room source changes
- ///
- void Room_CurrentSourceInfoChange(EssentialsRoomBase room, SourceListItem info, ChangeType type)
- {
- // Handle null. Nothing to do when switching from or to null
- if (info == null || info.SourceDevice == null)
- return;
-
- var dev = info.SourceDevice;
- if (type == ChangeType.WillChange)
- {
- if (SourceToFeedbackSigs.ContainsKey(dev))
- SourceToFeedbackSigs[dev].BoolValue = false;
- }
- else
- {
- if (SourceToFeedbackSigs.ContainsKey(dev))
- SourceToFeedbackSigs[dev].BoolValue = true;
- var name = (room == null ? "" : room.Name);
- CurrentRoomSourceNameSig.InputSig.StringValue = info.SourceDevice.Name;
- }
- }
-
- void FusionRoom_FusionStateChange(FusionBase device, FusionStateEventArgs args)
- {
-
- // The sig/UO method: Need separate handlers for fixed and user sigs, all flavors,
- // even though they all contain sigs.
-
- var sigData = (args.UserConfiguredSigDetail as BooleanSigDataFixedName);
- if (sigData != null)
- {
- var outSig = sigData.OutputSig;
- if (outSig.UserObject is Action)
- (outSig.UserObject as Action).Invoke(outSig.BoolValue);
- else if (outSig.UserObject is Action)
- (outSig.UserObject as Action).Invoke(outSig.UShortValue);
- else if (outSig.UserObject is Action)
- (outSig.UserObject as Action).Invoke(outSig.StringValue);
- return;
- }
-
- var attrData = (args.UserConfiguredSigDetail as BooleanSigData);
- if (attrData != null)
- {
- var outSig = attrData.OutputSig;
- if (outSig.UserObject is Action)
- (outSig.UserObject as Action).Invoke(outSig.BoolValue);
- else if (outSig.UserObject is Action)
- (outSig.UserObject as Action).Invoke(outSig.UShortValue);
- else if (outSig.UserObject is Action)
- (outSig.UserObject as Action).Invoke(outSig.StringValue);
- return;
- }
-
- }
- }
-
-
- public static class FusionRoomExtensions
- {
- ///
- /// Creates and returns a fusion attribute. The join number will match the established Simpl
- /// standard of 50+, and will generate a 50+ join in the RVI. It calls
- /// FusionRoom.AddSig with join number - 49
- ///
- /// The new attribute
- public static BooleanSigData CreateOffsetBoolSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
- {
- if (number < 50) throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
- number -= 49;
- fr.AddSig(eSigType.Bool, number, name, mask);
- return fr.UserDefinedBooleanSigDetails[number];
- }
-
- ///
- /// Creates and returns a fusion attribute. The join number will match the established Simpl
- /// standard of 50+, and will generate a 50+ join in the RVI. It calls
- /// FusionRoom.AddSig with join number - 49
- ///
- /// The new attribute
- public static UShortSigData CreateOffsetUshortSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
- {
- if (number < 50) throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
- number -= 49;
- fr.AddSig(eSigType.UShort, number, name, mask);
- return fr.UserDefinedUShortSigDetails[number];
- }
-
- ///
- /// Creates and returns a fusion attribute. The join number will match the established Simpl
- /// standard of 50+, and will generate a 50+ join in the RVI. It calls
- /// FusionRoom.AddSig with join number - 49
- ///
- /// The new attribute
- public static StringSigData CreateOffsetStringSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
- {
- if (number < 50) throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
- number -= 49;
- fr.AddSig(eSigType.String, number, name, mask);
- return fr.UserDefinedStringSigDetails[number];
- }
-
- ///
- /// Creates and returns a static asset
- ///
- /// the new asset
- public static FusionStaticAsset CreateStaticAsset(this FusionRoom fr, uint number, string name, string type, string instanceId)
- {
- Debug.Console(0, "Adding Fusion Static Asset '{0}' to slot {1} with GUID: '{2}'", name, number, instanceId);
-
- fr.AddAsset(eAssetType.StaticAsset, number, name, type, instanceId);
- return fr.UserConfigurableAssetDetails[number].Asset as FusionStaticAsset;
- }
-
- public static FusionOccupancySensor CreateOccupancySensorAsset(this FusionRoom fr, uint number, string name, string type, string instanceId)
- {
- Debug.Console(0, "Adding Fusion Occupancy Sensor Asset '{0}' to slot {1} with GUID: '{2}'", name, number, instanceId);
-
- fr.AddAsset(eAssetType.OccupancySensor, number, name, type, instanceId);
- return fr.UserConfigurableAssetDetails[number].Asset as FusionOccupancySensor;
- }
- }
-
- //************************************************************************************************
- ///
- /// Extensions to enhance Fusion room, asset and signal creation.
- ///
- public static class FusionStaticAssetExtensions
- {
- ///
- /// Tries to set a Fusion asset with the make and model of a device.
- /// If the provided Device is IMakeModel, will set the corresponding parameters on the fusion static asset.
- /// Otherwise, does nothing.
- ///
- public static void TrySetMakeModel(this FusionStaticAsset asset, Device device)
- {
- var mm = device as IMakeModel;
- if (mm != null)
- {
- asset.ParamMake.Value = mm.DeviceMake;
- asset.ParamModel.Value = mm.DeviceModel;
- }
- }
-
- ///
- /// Tries to attach the AssetError input on a Fusion asset to a Device's
- /// CommunicationMonitor.StatusChange event. Does nothing if the device is not
- /// IStatusMonitor
- ///
- ///
- ///
- public static void TryLinkAssetErrorToCommunication(this FusionStaticAsset asset, Device device)
- {
- if (device is ICommunicationMonitor)
- {
- var monitor = (device as ICommunicationMonitor).CommunicationMonitor;
- monitor.StatusChange += (o, a) =>
- {
- // Link connected and error inputs on asset
- asset.Connected.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
- asset.AssetError.InputSig.StringValue = a.Status.ToString();
- };
- // set current value
- asset.Connected.InputSig.BoolValue = monitor.Status == MonitorStatus.IsOk;
- asset.AssetError.InputSig.StringValue = monitor.Status.ToString();
- }
- }
- }
-
-
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Crestron.SimplSharp;
+using Crestron.SimplSharp.CrestronIO;
+using Crestron.SimplSharp.CrestronXml;
+using Crestron.SimplSharp.CrestronXml.Serialization;
+using Crestron.SimplSharp.CrestronXmlLinq;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.DeviceSupport;
+using Crestron.SimplSharpPro.Fusion;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+using PepperDash.Core;
+using PepperDash.Essentials;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Devices.Common;
+
+
+
+namespace PepperDash.Essentials.Fusion
+{
+ public class EssentialsHuddleSpaceFusionSystemController : Device
+ {
+ public event EventHandler ScheduleChange;
+ public event EventHandler MeetingEndWarning;
+ public event EventHandler NextMeetingBeginWarning;
+
+ FusionRoom FusionRoom;
+ EssentialsHuddleSpaceRoom Room;
+ Dictionary SourceToFeedbackSigs =
+ new Dictionary();
+
+ //BooleanSigData OccupancyStatusSig;
+
+ StatusMonitorCollection ErrorMessageRollUp;
+
+ StringSigData CurrentRoomSourceNameSig;
+
+ #region System Info Sigs
+ //StringSigData SystemName;
+ //StringSigData Model;
+ //StringSigData SerialNumber;
+ //StringSigData Uptime;
+ #endregion
+
+
+ #region Processor Info Sigs
+ StringSigData Ip1;
+ StringSigData Ip2;
+ StringSigData Gateway;
+ StringSigData Hostname;
+ StringSigData Domain;
+ StringSigData Dns1;
+ StringSigData Dns2;
+ StringSigData Mac1;
+ StringSigData Mac2;
+ StringSigData NetMask1;
+ StringSigData NetMask2;
+ StringSigData Firmware;
+
+ StringSigData[] Program = new StringSigData[10];
+ #endregion
+
+ #region Default Display Source Sigs
+
+ BooleanSigData[] Source = new BooleanSigData[10];
+
+ #endregion
+
+ RoomSchedule CurrentSchedule;
+
+ Event NextMeeting;
+
+ Event CurrentMeeting;
+
+ string RoomGuid
+ {
+ get
+ {
+ return GUIDs.RoomGuid;
+ }
+
+ }
+
+ uint IpId;
+
+ FusionRoomGuids GUIDs;
+
+ bool GuidFileExists;
+
+ bool IsRegisteredForSchedulePushNotifications = false;
+
+ CTimer PollTimer = null;
+
+ CTimer PushNotificationTimer = null;
+
+ // Default poll time is 5 min unless overridden by config value
+ public long SchedulePollInterval = 300000;
+
+ public long PushNotificationTimeout = 5000;
+
+ Dictionary FusionStaticAssets;
+
+ FusionOccupancySensorAsset FusionOccSensor;
+
+ //ScheduleResponseEvent NextMeeting;
+
+ public EssentialsHuddleSpaceFusionSystemController(EssentialsHuddleSpaceRoom room, uint ipId)
+ : base(room.Key + "-fusion")
+ {
+
+ Room = room;
+
+ IpId = ipId;
+
+ FusionStaticAssets = new Dictionary();
+
+ GUIDs = new FusionRoomGuids();
+
+ var mac = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0);
+
+ var slot = Global.ControlSystem.ProgramNumber;
+
+ string guidFilePath = string.Format(@"\NVRAM\Program{0}\{1}-FusionGuids.json", Global.ControlSystem.ProgramNumber, InitialParametersClass.ProgramIDTag);
+
+ GuidFileExists = File.Exists(guidFilePath);
+
+ if (GuidFileExists)
+ {
+ ReadGuidFile(guidFilePath);
+ }
+ else
+ {
+ GUIDs = new FusionRoomGuids(Room.Name, ipId, GUIDs.GenerateNewRoomGuid(slot, mac), FusionStaticAssets);
+ }
+
+ CreateSymbolAndBasicSigs(IpId);
+ SetUpSources();
+ SetUpCommunitcationMonitors();
+ SetUpDisplay();
+ SetUpError();
+ //SetUpOccupancy();
+
+ // Make it so!
+ FusionRVI.GenerateFileForAllFusionDevices();
+
+ GenerateGuidFile(guidFilePath);
+ }
+
+ ///
+ /// Generates the guid file in NVRAM. If the file already exists it will be overwritten.
+ ///
+ /// 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");
+
+ if (FusionOccSensor == null)
+ GUIDs = new FusionRoomGuids(Room.Name, IpId, RoomGuid, FusionStaticAssets);
+ else
+ GUIDs = new FusionRoomGuids(Room.Name, IpId, RoomGuid, FusionStaticAssets, FusionOccSensor);
+
+ 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);
+
+ GUIDs = JsonConvert.DeserializeObject(JSON);
+
+ IpId = GUIDs.IpId;
+
+ FusionStaticAssets = GUIDs.StaticAssets;
+
+ }
+
+ Debug.Console(0, this, "Fusion Guids successfully read from file:");
+
+ Debug.Console(1, this, "\nRoom Name: {0}\nIPID: {1:x}\n RoomGuid: {2}", Room.Name, IpId, RoomGuid);
+
+ foreach (KeyValuePair item in FusionStaticAssets)
+ {
+ Debug.Console(1, this, "\nAsset Name: {0}\nAsset No: {1}\n Guid: {2}", item.Value.Name, item.Value.SlotNumber, item.Value.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}", RoomGuid);
+
+ FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
+ FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();
+ FusionRoom.ExtenderFusionRoomDataReservedSigs.Use();
+
+ FusionRoom.Register();
+
+ 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);
+ CrestronConsole.AddNewConsoleCommand(CreateAsHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
+
+ // Room to fusion room
+ Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
+
+ // Moved to
+ CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(84, "Display 1 - Current Source", eSigIoMask.InputSigOnly);
+ // Don't think we need to get current status of this as nothing should be alive yet.
+ Room.CurrentSingleSourceChange += new SourceInfoChangeHandler(Room_CurrentSourceInfoChange);
+
+
+ FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction(Room.PowerOnToDefaultOrLastSource);
+ FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => Room.RunRouteAction("roomOff"));
+ // NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig);
+ 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;";
+
+ GetProcessorEthernetValues();
+
+ GetSystemInfo();
+
+ GetProcessorInfo();
+
+ CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
+ }
+
+ void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs)
+ {
+ if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp)
+ {
+ GetProcessorEthernetValues();
+ }
+ }
+
+ void GetSystemInfo()
+ {
+ //SystemName.InputSig.StringValue = Room.Name;
+ //Model.InputSig.StringValue = InitialParametersClass.ControllerPromptName;
+ //SerialNumber.InputSig.StringValue = InitialParametersClass.
+
+ string response = string.Empty;
+
+ var systemReboot = FusionRoom.CreateOffsetBoolSig(74, "Processor - Reboot", eSigIoMask.OutputSigOnly);
+ systemReboot.OutputSig.SetSigFalseAction(() => CrestronConsole.SendControlSystemCommand("reboot", ref response));
+ }
+
+ void GetProcessorEthernetValues()
+ {
+ Ip1 = FusionRoom.CreateOffsetStringSig(50, "Info - Processor - IP 1", eSigIoMask.InputSigOnly);
+ Ip2 = FusionRoom.CreateOffsetStringSig(51, "Info - Processor - IP 2", eSigIoMask.InputSigOnly);
+ Gateway = FusionRoom.CreateOffsetStringSig(52, "Info - Processor - Gateway", eSigIoMask.InputSigOnly);
+ Hostname = FusionRoom.CreateOffsetStringSig(53, "Info - Processor - Hostname", eSigIoMask.InputSigOnly);
+ Domain = FusionRoom.CreateOffsetStringSig(54, "Info - Processor - Domain", eSigIoMask.InputSigOnly);
+ Dns1 = FusionRoom.CreateOffsetStringSig(55, "Info - Processor - DNS 1", eSigIoMask.InputSigOnly);
+ Dns2 = FusionRoom.CreateOffsetStringSig(56, "Info - Processor - DNS 2", eSigIoMask.InputSigOnly);
+ Mac1 = FusionRoom.CreateOffsetStringSig(57, "Info - Processor - MAC 1", eSigIoMask.InputSigOnly);
+ Mac2 = FusionRoom.CreateOffsetStringSig(58, "Info - Processor - MAC 2", eSigIoMask.InputSigOnly);
+ NetMask1 = FusionRoom.CreateOffsetStringSig(59, "Info - Processor - Net Mask 1", eSigIoMask.InputSigOnly);
+ NetMask2 = FusionRoom.CreateOffsetStringSig(60, "Info - Processor - Net Mask 2", eSigIoMask.InputSigOnly);
+
+ // Interface =0
+ Ip1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0);
+ Gateway.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, 0);
+ Hostname.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0);
+ Domain.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, 0);
+
+ var dnsServers = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DNS_SERVER, 0).Split(',');
+ Dns1.InputSig.StringValue = dnsServers[0];
+ if (dnsServers.Length > 1)
+ Dns2.InputSig.StringValue = dnsServers[1];
+
+ Mac1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0);
+ NetMask1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, 0);
+
+ // Interface 1
+
+ if (InitialParametersClass.NumberOfEthernetInterfaces > 1) // Only get these values if the processor has more than 1 NIC
+ {
+ Ip2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 1);
+ Mac2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 1);
+ NetMask2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, 1);
+ }
+ }
+
+ void GetProcessorInfo()
+ {
+ //SystemName = FusionRoom.CreateOffsetStringSig(50, "Info - Processor - System Name", eSigIoMask.InputSigOnly);
+ //Model = FusionRoom.CreateOffsetStringSig(51, "Info - Processor - Model", eSigIoMask.InputSigOnly);
+ //SerialNumber = FusionRoom.CreateOffsetStringSig(52, "Info - Processor - Serial Number", eSigIoMask.InputSigOnly);
+ //Uptime = FusionRoom.CreateOffsetStringSig(53, "Info - Processor - Uptime", eSigIoMask.InputSigOnly);
+
+ Firmware = FusionRoom.CreateOffsetStringSig(61, "Info - Processor - Firmware", eSigIoMask.InputSigOnly);
+
+ for (int i = 0; i < Global.ControlSystem.NumProgramsSupported; i++)
+ {
+ var join = 62 + i;
+ var progNum = i + 1;
+ Program[i] = FusionRoom.CreateOffsetStringSig((uint)join, string.Format("Info - Processor - Program {0}", progNum), eSigIoMask.InputSigOnly);
+ }
+
+ Firmware.InputSig.StringValue = InitialParametersClass.FirmwareVersion;
+
+ //var programs = ProcessorProgReg.GetProcessorProgReg();
+
+ //for (int i = 1; i < Global.ControlSystem.NumProgramsSupported; i++)
+ //{
+ // var join = 62 + i;
+ // var progNum = i + 1;
+ // if (programs[i].Exists)
+ // Program[i].InputSig.StringValue = programs[i].Name;
+ //}
+
+ }
+
+ void GetTouchpanelInfo()
+ {
+ // TODO Get IP and Project Name from TP
+ }
+
+ void FusionRoom_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
+ {
+ if (args.DeviceOnLine)
+ {
+ CrestronEnvironment.Sleep(200);
+
+ // Send Push Notification Action request:
+
+ string requestID = "InitialPushRequest";
+
+
+ string actionRequest =
+ string.Format("\n{0}\n", requestID) +
+ "RegisterPushModel\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n";
+
+ Debug.Console(2, this, "Sending Fusion ActionRequest: \n{0}", actionRequest);
+
+ FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = actionRequest;
+
+
+ // Request current Fusion Server Time
+
+ string timeRequestID = "TimeRequest";
+
+ string timeRequest = string.Format("{0}", timeRequestID);
+
+ FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQuery.StringValue = timeRequest;
+ }
+
+ }
+
+ ///
+ /// 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(object callbackObject)
+ {
+ DateTime now = DateTime.Today;
+
+ string currentTime = now.ToString("s");
+
+ string requestTest =
+ string.Format("FullSchedleRequest{0}{1}24", RoomGuid, currentTime);
+
+ Debug.Console(2, this, "Sending Fusion ScheduleQuery: \n{0}", requestTest);
+
+ FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleQuery.StringValue = requestTest;
+
+ if (IsRegisteredForSchedulePushNotifications)
+ PushNotificationTimer.Stop();
+ }
+
+ ///
+ /// Wrapper method to allow console commands to modify the current meeting end time
+ ///
+ /// meetingID extendTime
+ public void ModifyMeetingEndTimeConsoleHelper(string command)
+ {
+ string requestID;
+ string meetingID = null;
+ int extendMinutes = -1;
+
+ requestID = "ModifyMeetingTest12345";
+
+ try
+ {
+ var tokens = command.Split(' ');
+
+ meetingID = tokens[0];
+ extendMinutes = Int32.Parse(tokens[1]);
+
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Error parsing console command: {0}", e);
+ }
+
+ ModifyMeetingEndTime(requestID, extendMinutes);
+
+ }
+
+ ///
+ /// Ends or Extends the current meeting by the specified number of minutes.
+ ///
+ /// Number of minutes to extend the meeting. A value of 0 will end the meeting.
+ public void ModifyMeetingEndTime(string requestID, int extendMinutes)
+ {
+ if(CurrentMeeting == null)
+ {
+ Debug.Console(1, this, "No meeting in progress. Unable to modify end time.");
+ return;
+ }
+
+ if (extendMinutes > -1)
+ {
+ if(extendMinutes > 0)
+ {
+ var extendTime = CurrentMeeting.dtEnd - DateTime.Now;
+ double extendMinutesRaw = extendTime.TotalMinutes;
+
+ extendMinutes = extendMinutes + (int)Math.Round(extendMinutesRaw);
+ }
+
+
+ string requestTest = string.Format(
+ "{0}{1}MeetingChange"
+ , requestID, RoomGuid, CurrentMeeting.MeetingID, extendMinutes);
+
+ Debug.Console(1, this, "Sending MeetingChange Request: \n{0}", requestTest);
+
+ FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = requestTest;
+ }
+ else
+ {
+ Debug.Console(1, this, "Invalid time specified");
+ }
+
+
+ }
+
+ ///
+ /// Creates and Ad Hoc meeting with a duration of 1 hour, or until the next meeting if in less than 1 hour.
+ ///
+ public void CreateAsHocMeeting(string command)
+ {
+ string requestID = "CreateAdHocMeeting";
+
+ DateTime now = DateTime.Now.AddMinutes(1);
+
+ now.AddSeconds(-now.Second);
+
+ // Assume 1 hour meeting if possible
+ DateTime dtEnd = now.AddHours(1);
+
+ // Check if room is available for 1 hour before next meeting
+ if (NextMeeting != null)
+ {
+ var roomAvailable = NextMeeting.dtEnd.Subtract(dtEnd);
+
+ if (roomAvailable.TotalMinutes < 60)
+ {
+ /// Room not available for full hour, book until next meeting starts
+ dtEnd = NextMeeting.dtEnd;
+ }
+ }
+
+ string createMeetingRequest =
+ "" +
+ string.Format("{0}", requestID) +
+ string.Format("{0}", RoomGuid) +
+ "" +
+ string.Format("{0}", now.ToString("s")) +
+ string.Format("{0}", dtEnd.ToString("s")) +
+ "AdHoc Meeting" +
+ "Room User" +
+ "Example Message" +
+ "" +
+ "";
+
+ Debug.Console(2, this, "Sending CreateMeeting Request: \n{0}", createMeetingRequest);
+
+ FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateMeeting.StringValue = createMeetingRequest;
+
+ //Debug.Console(1, this, "Sending CreateMeeting Request: \n{0}", command);
+
+ //FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateMeeting.StringValue = command;
+
+ }
+
+ ///
+ /// Event handler method for Device Extender sig changes
+ ///
+ ///
+ ///
+ void ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
+ {
+ Debug.Console(2, this, "Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue);
+
+
+ if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQueryResponse)
+ {
+ try
+ {
+ XmlDocument message = new XmlDocument();
+
+ message.LoadXml(args.Sig.StringValue);
+
+ var actionResponse = message["ActionResponse"];
+
+ if (actionResponse != null)
+ {
+ var requestID = actionResponse["RequestID"];
+
+ if (requestID.InnerText == "InitialPushRequest")
+ {
+ if (actionResponse["ActionID"].InnerText == "RegisterPushModel")
+ {
+ var parameters = actionResponse["Parameters"];
+
+ foreach (XmlElement parameter in parameters)
+ {
+ if (parameter.HasAttributes)
+ {
+ var attributes = parameter.Attributes;
+
+ if (attributes["ID"].Value == "Registered")
+ {
+ var isRegistered = Int32.Parse(attributes["Value"].Value);
+
+ if (isRegistered == 1)
+ {
+ IsRegisteredForSchedulePushNotifications = true;
+
+ if (PollTimer != null && !PollTimer.Disposed)
+ {
+ PollTimer.Stop();
+ PollTimer.Dispose();
+ }
+
+ PushNotificationTimer = new CTimer(RequestFullRoomSchedule, null, PushNotificationTimeout, PushNotificationTimeout);
+
+ PushNotificationTimer.Reset(PushNotificationTimeout, PushNotificationTimeout);
+ }
+ else if (isRegistered == 0)
+ {
+ IsRegisteredForSchedulePushNotifications = false;
+
+ if (PushNotificationTimer != null && !PushNotificationTimer.Disposed)
+ {
+ PushNotificationTimer.Stop();
+ PushNotificationTimer.Dispose();
+ }
+
+ PollTimer = new CTimer(RequestFullRoomSchedule, null, SchedulePollInterval, SchedulePollInterval);
+
+ PollTimer.Reset(SchedulePollInterval, SchedulePollInterval);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Error parsing ActionQueryResponse: {0}", e);
+ }
+ }
+ else if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQueryResponse)
+ {
+ try
+ {
+ XmlDocument message = new XmlDocument();
+
+ message.LoadXml(args.Sig.StringValue);
+
+ var localDateTimeResponse = message["LocalTimeResponse"];
+
+ if (localDateTimeResponse != null)
+ {
+ var localDateTime = localDateTimeResponse["LocalDateTime"];
+
+ if (localDateTime != null)
+ {
+ var tempLocalDateTime = localDateTime.InnerText;
+
+ DateTime currentTime = DateTime.Parse(tempLocalDateTime);
+
+ Debug.Console(1, this, "DateTime from Fusion Server: {0}", currentTime);
+
+ // Parse time and date from response and insert values
+ CrestronEnvironment.SetTimeAndDate((ushort)currentTime.Hour, (ushort)currentTime.Minute, (ushort)currentTime.Second, (ushort)currentTime.Month, (ushort)currentTime.Day, (ushort)currentTime.Year);
+
+ Debug.Console(1, this, "Processor time set to {0}", CrestronEnvironment.GetLocalTime());
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Error parsing LocalDateTimeQueryResponse: {0}", e);
+ }
+ }
+ }
+
+ ///
+ /// Event handler method for Device Extender sig changes
+ ///
+ ///
+ ///
+ void FusionRoomSchedule_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
+ {
+ Debug.Console(2, this, "Scehdule Response 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);
+
+ var response = message["ScheduleResponse"];
+
+ if (response != null)
+ {
+ // Check for push notification
+ if (response["RequestID"].InnerText == "RVRequest")
+ {
+ var action = response["Action"];
+
+ if (action.OuterXml.IndexOf("RequestSchedule") > -1)
+ {
+ PushNotificationTimer.Reset(PushNotificationTimeout, PushNotificationTimeout);
+ }
+ }
+ else // Not a push notification
+ {
+ CurrentSchedule = new RoomSchedule(); // Clear Current Schedule
+ CurrentMeeting = null; // Clear Current Meeting
+ NextMeeting = null; // Clear Next Meeting
+
+ bool isNextMeeting = false;
+
+ 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(2, 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);
+
+ // Check is this is the current event
+ if (tempEvent.dtStart <= DateTime.Now && tempEvent.dtEnd >= DateTime.Now)
+ {
+ CurrentMeeting = tempEvent; // Set Current Meeting
+ isNextMeeting = true; // Flag that next element is next meeting
+ }
+
+ if (isNextMeeting)
+ {
+ NextMeeting = tempEvent; // Set Next Meeting
+ isNextMeeting = false;
+ }
+
+ CurrentSchedule.Meetings.Add(tempEvent);
+ }
+
+ }
+
+ PrintTodaysSchedule();
+
+ if (!IsRegisteredForSchedulePushNotifications)
+ PollTimer.Reset(SchedulePollInterval, SchedulePollInterval);
+
+ // Fire Schedule Change Event
+ var handler = ScheduleChange;
+
+ if (handler != null)
+ {
+ handler(this, new ScheduleChangeEventArgs() { Schedule = CurrentSchedule });
+ }
+
+ }
+ }
+
+
+
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Error parsing ScheduleResponse: {0}", e);
+ }
+ }
+ else if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateResponse)
+ {
+ Debug.Console(2, this, "Create Meeting Response Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue);
+ }
+
+ }
+
+ ///
+ /// Prints today's schedule to console for debugging
+ ///
+ void PrintTodaysSchedule()
+ {
+ if (Debug.Level > 1)
+ {
+ if (CurrentSchedule.Meetings.Count > 0)
+ {
+ Debug.Console(1, this, "Today's Schedule for '{0}'\n", Room.Name);
+
+ foreach (Event e in CurrentSchedule.Meetings)
+ {
+ Debug.Console(1, this, "Subject: {0}", e.Subject);
+ Debug.Console(1, this, "Organizer: {0}", e.Organizer);
+ Debug.Console(1, this, "MeetingID: {0}", e.MeetingID);
+ Debug.Console(1, this, "Start Time: {0}", e.dtStart);
+ Debug.Console(1, this, "End Time: {0}", e.dtEnd);
+ Debug.Console(1, this, "Duration: {0}\n", e.DurationInMinutes);
+ }
+ }
+ }
+ }
+
+ void SetUpSources()
+ {
+ // Sources
+ var dict = ConfigReader.ConfigObject.GetSourceListForKey(Room.SourceListKey);
+ if (dict != null)
+ {
+ // NEW PROCESS:
+ // Make these lists and insert the fusion attributes by iterating these
+ var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
+ uint i = 1;
+ foreach (var kvp in setTopBoxes)
+ {
+ TryAddRouteActionSigs("Display 1 - Source TV " + i, 188 + i, kvp.Key, kvp.Value.SourceDevice);
+ i++;
+ if (i > 5) // We only have five spots
+ break;
+ }
+
+ var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
+ i = 1;
+ foreach (var kvp in discPlayers)
+ {
+ TryAddRouteActionSigs("Display 1 - Source DVD " + i, 181 + i, kvp.Key, kvp.Value.SourceDevice);
+ i++;
+ if (i > 5) // We only have five spots
+ break;
+ }
+
+ var laptops = dict.Where(d => d.Value.SourceDevice is Laptop);
+ i = 1;
+ foreach (var kvp in laptops)
+ {
+ TryAddRouteActionSigs("Display 1 - Source Laptop " + i, 166 + i, kvp.Key, kvp.Value.SourceDevice);
+ i++;
+ if (i > 10) // We only have ten spots???
+ break;
+ }
+
+ foreach (var kvp in dict)
+ {
+ var usageDevice = kvp.Value.SourceDevice as IUsageTracking;
+
+ if (usageDevice != null)
+ {
+ usageDevice.UsageTracker = new UsageTracking(usageDevice as Device);
+ usageDevice.UsageTracker.UsageIsTracked = true;
+ usageDevice.UsageTracker.DeviceUsageEnded += new EventHandler(UsageTracker_DeviceUsageEnded);
+ }
+ }
+
+ }
+ else
+ {
+ Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'",
+ Room.SourceListKey, Room.Key);
+ }
+ }
+
+ ///
+ /// Collects usage data from source and sends to Fusion
+ ///
+ ///
+ ///
+ void UsageTracker_DeviceUsageEnded(object sender, DeviceUsageEventArgs e)
+ {
+ var deviceTracker = sender as UsageTracking;
+
+ var configDevice = ConfigReader.ConfigObject.Devices.Where(d => d.Key.Equals(deviceTracker.Parent));
+
+ string group = ConfigReader.GetGroupForDeviceKey(deviceTracker.Parent.Key);
+
+ string currentMeetingId = "-";
+
+ if (CurrentMeeting != null)
+ currentMeetingId = CurrentMeeting.MeetingID;
+
+ //String Format: "USAGE||[Date YYYY-MM-DD]||[Time HH-mm-ss]||TIME||[Asset_Type]||[Asset_Name]||[Minutes_used]||[Asset_ID]||[Meeting_ID]"
+ // [Asset_ID] property does not appear to be used in Crestron SSI examples. They are sending "-" instead so that's what is replicated here
+ string deviceUsage = string.Format("USAGE||{0}||{1}||TIME||{2}||{3}||-||{4}||-||{5}||{6}||\r\n", e.UsageEndTime.ToString("yyyy-MM-dd"), e.UsageEndTime.ToString("HH:mm:ss"),
+ group, deviceTracker.Parent.Name, e.MinutesUsed, "-", currentMeetingId);
+
+ Debug.Console(1, this, "Device usage for: {0} ended at {1}. In use for {2} minutes", deviceTracker.Parent.Name, e.UsageEndTime, e.MinutesUsed);
+
+ FusionRoom.DeviceUsage.InputSig.StringValue = deviceUsage;
+
+ Debug.Console(1, this, "Device usage string: {0}", deviceUsage);
+ }
+
+
+ void TryAddRouteActionSigs(string attrName, uint attrNum, string routeKey, Device pSrc)
+ {
+ Debug.Console(2, this, "Creating attribute '{0}' with join {1} for source {2}",
+ attrName, attrNum, pSrc.Key);
+ try
+ {
+ var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputOutputSig);
+ // Need feedback when this source is selected
+ // Event handler, added below, will compare source changes with this sig dict
+ SourceToFeedbackSigs.Add(pSrc, sigD.InputSig);
+
+ // And respond to selection in Fusion
+ sigD.OutputSig.SetSigFalseAction(() => Room.RunRouteAction(routeKey));
+ }
+ catch (Exception)
+ {
+ Debug.Console(2, this, "Error creating Fusion signal {0} {1} for device '{2}'. THIS NEEDS REWORKING", attrNum, attrName, pSrc.Key);
+ }
+ }
+
+ ///
+ ///
+ ///
+ void SetUpCommunitcationMonitors()
+ {
+ // Attach to all room's devices with monitors.
+ //foreach (var dev in DeviceManager.Devices)
+ foreach (var dev in DeviceManager.GetDevices())
+ {
+ if (!(dev is ICommunicationMonitor))
+ continue;
+
+ var keyNum = ExtractNumberFromKey(dev.Key);
+ if (keyNum == -1)
+ {
+ Debug.Console(1, this, "WARNING: Cannot link device '{0}' to numbered Fusion monitoring attributes",
+ dev.Key);
+ continue;
+ }
+ string attrName = null;
+ uint attrNum = Convert.ToUInt32(keyNum);
+
+ if (dev is EssentialsTouchpanelController)
+ {
+ if ((dev as EssentialsTouchpanelController).Panel is Crestron.SimplSharpPro.DeviceSupport.TswFt5Button)
+ {
+ if (attrNum > 10)
+ continue;
+ attrName = "Online - Touch Panel " + attrNum;
+ attrNum += 150;
+ }
+ else if ((dev as EssentialsTouchpanelController).Panel is Crestron.SimplSharpPro.UI.XpanelForSmartGraphics)
+ {
+ if (attrNum > 10)
+ continue;
+ attrName = "Online - XPanel " + attrNum;
+ attrNum += 160;
+ }
+ }
+
+ //else
+ if (dev is DisplayBase)
+ {
+ if (attrNum > 10)
+ continue;
+ attrName = "Online - Display " + attrNum;
+ attrNum += 170;
+ }
+ //else if (dev is DvdDeviceBase)
+ //{
+ // if (attrNum > 5)
+ // continue;
+ // attrName = "Device Ok - DVD " + attrNum;
+ // attrNum += 260;
+ //}
+ // add set top box
+
+ // add Cresnet roll-up
+
+ // add DM-devices roll-up
+
+ if (attrName != null)
+ {
+ // Link comm status to sig and update
+ var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputSigOnly);
+ var smd = dev as ICommunicationMonitor;
+ sigD.InputSig.BoolValue = smd.CommunicationMonitor.Status == MonitorStatus.IsOk;
+ smd.CommunicationMonitor.StatusChange += (o, a) =>
+ { sigD.InputSig.BoolValue = a.Status == MonitorStatus.IsOk; };
+ Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", dev.Key, attrName);
+ }
+ }
+ }
+
+ void SetUpDisplay()
+ {
+ try
+ {
+ //Setup Display Usage Monitoring
+
+ var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
+
+ // Consider updating this in multiple display systems
+
+ foreach (DisplayBase display in displays)
+ {
+ display.UsageTracker = new UsageTracking(display);
+ display.UsageTracker.UsageIsTracked = true;
+ display.UsageTracker.DeviceUsageEnded += new EventHandler(UsageTracker_DeviceUsageEnded);
+ }
+
+ var defaultDisplay = Room.DefaultDisplay as DisplayBase;
+ if (defaultDisplay == null)
+ {
+ Debug.Console(1, this, "Cannot link null display to Fusion");
+ return;
+ }
+
+ var dispPowerOnAction = new Action(b => { if (!b) defaultDisplay.PowerOn(); });
+ var dispPowerOffAction = new Action(b => { if (!b) defaultDisplay.PowerOff(); });
+
+ // Display to fusion room sigs
+ FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
+ FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
+ defaultDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
+ if (defaultDisplay is IDisplayUsage)
+ (defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
+
+
+
+ MapDisplayToRoomJoins(1, 158, defaultDisplay);
+
+
+ var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
+
+ //Check for existing asset in GUIDs collection
+
+ var tempAsset = new FusionAsset();
+
+ if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
+ {
+ tempAsset = FusionStaticAssets[deviceConfig.Uid];
+ }
+ else
+ {
+ // Create a new asset
+ tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), defaultDisplay.Name, "Display", "");
+ FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
+ }
+
+ var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
+ dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
+ dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
+ defaultDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
+ // NO!! display.PowerIsOn.LinkComplementInputSig(dispAsset.PowerOff.InputSig);
+ // Use extension methods
+ dispAsset.TrySetMakeModel(defaultDisplay);
+ dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Error setting up display in Fusion: {0}", e);
+ }
+
+ }
+
+ ///
+ /// Maps room attributes to a display at a specified index
+ ///
+ ///
+ /// a
+ void MapDisplayToRoomJoins(int displayIndex, int joinOffset, DisplayBase display)
+ {
+ string displayName = string.Format("Display {0} - ", displayIndex);
+
+
+ if(display == Room.DefaultDisplay)
+ {
+ // Display volume
+ var defaultDisplayVolume = FusionRoom.CreateOffsetUshortSig(50, "Volume - Fader01", eSigIoMask.InputOutputSig);
+ defaultDisplayVolume.OutputSig.UserObject = new Action(b => (display as IBasicVolumeWithFeedback).SetVolume(b));
+ (display as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(defaultDisplayVolume.InputSig);
+
+ // Power on
+ var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
+ defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOn(); });
+ display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
+
+ // Power Off
+ var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
+ defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOff(); }); ;
+ display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
+
+ // Current Source
+ var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
+ defaultDisplaySourceNone.OutputSig.UserObject = new Action(b => { if (!b) Room.RunRouteAction("roomOff"); }); ;
+
+ //var dict = ConfigReader.ConfigObject.GetSourceListForKey(Room.SourceListKey);
+
+ //foreach (var item in dict)
+ //{
+ // if(item.Key != "roomOff")
+ // {
+ // var defaultDisplaySource = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + (uint)item.Value.Order + 9 , string.Format("{0}Source {1}", displayIndex, item.Value.Order), eSigIoMask.InputOutputSig);
+ // defaultDisplaySource.OutputSig.UserObject = new Action(b => { if (!b) Room.RunRouteAction(item.Key); });
+
+ // //defaultDisplaySource.InputSig = Source[item.Value.Order].InputSig;
+ // }
+
+ //}
+ }
+ }
+
+ //void Room_CurrentSingleSourceChange(EssentialsRoomBase room, SourceListItem info, ChangeType type)
+ //{
+ // for (int i = 1; i <= Source.Length; i++)
+ // {
+ // Source[i].InputSig.BoolValue = false;
+ // }
+
+ // Source[info.Order].InputSig.BoolValue = true;
+
+ // // Need to check for current source key against source list and update Source[] BooleanSigData as appropriate
+
+ //}
+
+ void SetUpError()
+ {
+ // Roll up ALL device errors
+ ErrorMessageRollUp = new StatusMonitorCollection(this);
+ foreach (var dev in DeviceManager.GetDevices())
+ {
+ var md = dev as ICommunicationMonitor;
+ if (md != null)
+ {
+ ErrorMessageRollUp.AddMonitor(md.CommunicationMonitor);
+ Debug.Console(2, this, "Adding '{0}' to room's overall error monitor", md.CommunicationMonitor.Parent.Key);
+ }
+ }
+ ErrorMessageRollUp.Start();
+ FusionRoom.ErrorMessage.InputSig.StringValue = ErrorMessageRollUp.Message;
+ ErrorMessageRollUp.StatusChange += (o, a) =>
+ {
+ FusionRoom.ErrorMessage.InputSig.StringValue = ErrorMessageRollUp.Message;
+ };
+
+ }
+
+ void SetUpOccupancy()
+ {
+
+ // Need to have the room occupancy object first and somehow determine the slot number of the Occupancy asset but will not be able to use the UID from config likely.
+ // Consider defining an object just for Room Occupancy (either eAssetType.Occupancy Sensor (local) or eAssetType.RemoteOccupancySensor (from Fusion sched. panel)) and reserving slot 4 for that asset (statics would start at 5)
+
+ //if (Room.OccupancyObj != null)
+ //{
+
+ var tempOccAsset = GUIDs.OccupancyAsset;
+
+ if(tempOccAsset == null)
+ {
+ FusionOccSensor = new FusionOccupancySensorAsset(eAssetType.OccupancySensor);
+ tempOccAsset = FusionOccSensor;
+ }
+
+ var occSensorAsset = FusionRoom.CreateOccupancySensorAsset(tempOccAsset.SlotNumber, tempOccAsset.Name, "Occupancy Sensor", tempOccAsset.InstanceId);
+
+ occSensorAsset.RoomOccupied.AddSigToRVIFile = true;
+
+ var occSensorShutdownMinutes = FusionRoom.CreateOffsetUshortSig(70, "Occ Shutdown - Minutes", eSigIoMask.InputOutputSig);
+
+ // Tie to method on occupancy object
+ //occSensorShutdownMinutes.OutputSig.UserObject(new Action(ushort)(b => Room.OccupancyObj.SetShutdownMinutes(b));
+
+
+ // use Room.OccObject.RoomOccupiedFeedback.LinkInputSig(occSensorAsset.InputSig);
+ //}
+ }
+
+ ///
+ /// Helper to get the number from the end of a device's key string
+ ///
+ /// -1 if no number matched
+ int ExtractNumberFromKey(string key)
+ {
+ var capture = System.Text.RegularExpressions.Regex.Match(key, @"\D+(\d+)");
+ if (!capture.Success)
+ return -1;
+ else return Convert.ToInt32(capture.Groups[1].Value);
+ }
+
+ ///
+ /// Event handler for when room source changes
+ ///
+ void Room_CurrentSourceInfoChange(EssentialsRoomBase room, SourceListItem info, ChangeType type)
+ {
+ // Handle null. Nothing to do when switching from or to null
+ if (info == null || info.SourceDevice == null)
+ return;
+
+ var dev = info.SourceDevice;
+ if (type == ChangeType.WillChange)
+ {
+ if (SourceToFeedbackSigs.ContainsKey(dev))
+ SourceToFeedbackSigs[dev].BoolValue = false;
+ }
+ else
+ {
+ if (SourceToFeedbackSigs.ContainsKey(dev))
+ SourceToFeedbackSigs[dev].BoolValue = true;
+ var name = (room == null ? "" : room.Name);
+ CurrentRoomSourceNameSig.InputSig.StringValue = info.SourceDevice.Name;
+ }
+ }
+
+ void FusionRoom_FusionStateChange(FusionBase device, FusionStateEventArgs args)
+ {
+
+ // The sig/UO method: Need separate handlers for fixed and user sigs, all flavors,
+ // even though they all contain sigs.
+
+ var sigData = (args.UserConfiguredSigDetail as BooleanSigDataFixedName);
+ if (sigData != null)
+ {
+ var outSig = sigData.OutputSig;
+ if (outSig.UserObject is Action)
+ (outSig.UserObject as Action).Invoke(outSig.BoolValue);
+ else if (outSig.UserObject is Action)
+ (outSig.UserObject as Action).Invoke(outSig.UShortValue);
+ else if (outSig.UserObject is Action)
+ (outSig.UserObject as Action).Invoke(outSig.StringValue);
+ return;
+ }
+
+ var attrData = (args.UserConfiguredSigDetail as BooleanSigData);
+ if (attrData != null)
+ {
+ var outSig = attrData.OutputSig;
+ if (outSig.UserObject is Action)
+ (outSig.UserObject as Action).Invoke(outSig.BoolValue);
+ else if (outSig.UserObject is Action)
+ (outSig.UserObject as Action).Invoke(outSig.UShortValue);
+ else if (outSig.UserObject is Action)
+ (outSig.UserObject as Action).Invoke(outSig.StringValue);
+ return;
+ }
+
+ }
+ }
+
+
+ public static class FusionRoomExtensions
+ {
+ ///
+ /// Creates and returns a fusion attribute. The join number will match the established Simpl
+ /// standard of 50+, and will generate a 50+ join in the RVI. It calls
+ /// FusionRoom.AddSig with join number - 49
+ ///
+ /// The new attribute
+ public static BooleanSigData CreateOffsetBoolSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
+ {
+ if (number < 50) throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
+ number -= 49;
+ fr.AddSig(eSigType.Bool, number, name, mask);
+ return fr.UserDefinedBooleanSigDetails[number];
+ }
+
+ ///
+ /// Creates and returns a fusion attribute. The join number will match the established Simpl
+ /// standard of 50+, and will generate a 50+ join in the RVI. It calls
+ /// FusionRoom.AddSig with join number - 49
+ ///
+ /// The new attribute
+ public static UShortSigData CreateOffsetUshortSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
+ {
+ if (number < 50) throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
+ number -= 49;
+ fr.AddSig(eSigType.UShort, number, name, mask);
+ return fr.UserDefinedUShortSigDetails[number];
+ }
+
+ ///
+ /// Creates and returns a fusion attribute. The join number will match the established Simpl
+ /// standard of 50+, and will generate a 50+ join in the RVI. It calls
+ /// FusionRoom.AddSig with join number - 49
+ ///
+ /// The new attribute
+ public static StringSigData CreateOffsetStringSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
+ {
+ if (number < 50) throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
+ number -= 49;
+ fr.AddSig(eSigType.String, number, name, mask);
+ return fr.UserDefinedStringSigDetails[number];
+ }
+
+ ///
+ /// Creates and returns a static asset
+ ///
+ /// the new asset
+ public static FusionStaticAsset CreateStaticAsset(this FusionRoom fr, uint number, string name, string type, string instanceId)
+ {
+ Debug.Console(0, "Adding Fusion Static Asset '{0}' to slot {1} with GUID: '{2}'", name, number, instanceId);
+
+ fr.AddAsset(eAssetType.StaticAsset, number, name, type, instanceId);
+ return fr.UserConfigurableAssetDetails[number].Asset as FusionStaticAsset;
+ }
+
+ public static FusionOccupancySensor CreateOccupancySensorAsset(this FusionRoom fr, uint number, string name, string type, string instanceId)
+ {
+ Debug.Console(0, "Adding Fusion Occupancy Sensor Asset '{0}' to slot {1} with GUID: '{2}'", name, number, instanceId);
+
+ fr.AddAsset(eAssetType.OccupancySensor, number, name, type, instanceId);
+ return fr.UserConfigurableAssetDetails[number].Asset as FusionOccupancySensor;
+ }
+ }
+
+ //************************************************************************************************
+ ///
+ /// Extensions to enhance Fusion room, asset and signal creation.
+ ///
+ public static class FusionStaticAssetExtensions
+ {
+ ///
+ /// Tries to set a Fusion asset with the make and model of a device.
+ /// If the provided Device is IMakeModel, will set the corresponding parameters on the fusion static asset.
+ /// Otherwise, does nothing.
+ ///
+ public static void TrySetMakeModel(this FusionStaticAsset asset, Device device)
+ {
+ var mm = device as IMakeModel;
+ if (mm != null)
+ {
+ asset.ParamMake.Value = mm.DeviceMake;
+ asset.ParamModel.Value = mm.DeviceModel;
+ }
+ }
+
+ ///
+ /// Tries to attach the AssetError input on a Fusion asset to a Device's
+ /// CommunicationMonitor.StatusChange event. Does nothing if the device is not
+ /// IStatusMonitor
+ ///
+ ///
+ ///
+ public static void TryLinkAssetErrorToCommunication(this FusionStaticAsset asset, Device device)
+ {
+ if (device is ICommunicationMonitor)
+ {
+ var monitor = (device as ICommunicationMonitor).CommunicationMonitor;
+ monitor.StatusChange += (o, a) =>
+ {
+ // Link connected and error inputs on asset
+ asset.Connected.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
+ asset.AssetError.InputSig.StringValue = a.Status.ToString();
+ };
+ // set current value
+ asset.Connected.InputSig.BoolValue = monitor.Status == MonitorStatus.IsOk;
+ asset.AssetError.InputSig.StringValue = monitor.Status.ToString();
+ }
+ }
+ }
+
+
}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs.orig b/Essentials/PepperDashEssentials/OTHER/Fusion/FusionSystemController.cs.orig
similarity index 100%
rename from Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs.orig
rename to Essentials/PepperDashEssentials/OTHER/Fusion/FusionSystemController.cs.orig
diff --git a/Essentials/PepperDashEssentials/PepperDashEssentials.csproj b/Essentials/PepperDashEssentials/PepperDashEssentials.csproj
index cafe9b6b..800d772c 100644
--- a/Essentials/PepperDashEssentials/PepperDashEssentials.csproj
+++ b/Essentials/PepperDashEssentials/PepperDashEssentials.csproj
@@ -134,11 +134,11 @@
-
-
-
+
+
+
-
+
@@ -165,7 +165,7 @@
-
+
@@ -193,9 +193,6 @@
-
-
-
diff --git a/Essentials/PepperDashEssentials/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs b/Essentials/PepperDashEssentials/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs
index 1d9051d5..3f0b8b77 100644
--- a/Essentials/PepperDashEssentials/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs
+++ b/Essentials/PepperDashEssentials/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs
@@ -13,5 +13,6 @@ namespace PepperDash.Essentials.Room.Config
public string DefaultAudioKey { get; set; }
public string SourceListKey { get; set; }
public string DefaultSourceItem { get; set; }
+ public string VideoCodecKey { get; set; }
}
}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs b/Essentials/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs
index 7761d367..e2b3f5d0 100644
--- a/Essentials/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs
+++ b/Essentials/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs
@@ -59,7 +59,11 @@ namespace PepperDash.Essentials.Room.Config
var props = JsonConvert.DeserializeObject
(this.Properties.ToString());
var disp = DeviceManager.GetDeviceForKey(props.DefaultDisplayKey) as IRoutingSinkWithSwitching;
- var rm = new EssentialsHuddleVtc1Room(Key, Name, disp, disp, props);
+
+ var codec = DeviceManager.GetDeviceForKey(props.VideoCodecKey) as
+ PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
+
+ var rm = new EssentialsHuddleVtc1Room(Key, Name, disp, disp, codec, props);
rm.LogoUrl = props.Logo.GetUrl();
rm.SourceListKey = props.SourceListKey;
rm.DefaultSourceItem = props.DefaultSourceItem;
diff --git a/Essentials/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/Essentials/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs
index 60bed37e..d875d674 100644
--- a/Essentials/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs
+++ b/Essentials/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs
@@ -7,6 +7,7 @@ using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.Config;
+using PepperDash.Essentials.Devices.Common.VideoCodec;
namespace PepperDash.Essentials
{
@@ -71,6 +72,8 @@ namespace PepperDash.Essentials
public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
+ public VideoCodecBase VideoCodec { get; private set; }
+
public bool ExcludeFromGlobalFunctions { get; set; }
///
@@ -152,11 +155,12 @@ namespace PepperDash.Essentials
///
///
public EssentialsHuddleVtc1Room(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
- IRoutingSinkNoSwitching defaultAudio, EssentialsHuddleVtc1PropertiesConfig config)
+ IRoutingSinkNoSwitching defaultAudio, VideoCodecBase vc, EssentialsHuddleVtc1PropertiesConfig config)
: base(key, name)
{
Config = config;
DefaultDisplay = defaultDisplay;
+ VideoCodec = vc;
DefaultAudioDevice = defaultAudio;
if (defaultAudio is IBasicVolumeControls)
DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
diff --git a/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs
index 6398a2c5..21130a5f 100644
--- a/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs
+++ b/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs
@@ -154,6 +154,9 @@ namespace PepperDash.Essentials
{
Debug.Console(0, this, "Adding huddle space driver");
var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, props);
+ var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(Panel,
+ (room as EssentialsHuddleVtc1Room).VideoCodec);
+ avDriver.SetVideoCodecDriver(codecDriver);
avDriver.CurrentRoom = room as EssentialsHuddleVtc1Room;
avDriver.DefaultRoomKey = props.DefaultRoomKey;
mainDriver.AvDriver = avDriver;
diff --git a/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs b/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
index b54e40f6..c055ff77 100644
--- a/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
+++ b/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
@@ -143,6 +143,10 @@ namespace PepperDash.Essentials
/// 1235
///
public const uint VCStagingCameraPress = 1235;
+ ///
+ /// 1236
+ ///
+ public const uint VCStagingConnectEnable = 1236;
//******************************************************
// Keyboard
diff --git a/Essentials/PepperDashEssentials/UI/JoinConstants/UIUshortJoin.cs b/Essentials/PepperDashEssentials/UI/JoinConstants/UIUshortJoin.cs
index 1d37dca4..70f03b0a 100644
--- a/Essentials/PepperDashEssentials/UI/JoinConstants/UIUshortJoin.cs
+++ b/Essentials/PepperDashEssentials/UI/JoinConstants/UIUshortJoin.cs
@@ -5,6 +5,12 @@
///
public class UIUshortJoin
{
+ // Video Codec
+ ///
+ /// 1234 - 0 = Connect, 1 = End
+ ///
+ public const uint VCStagingConnectButtonMode = 1234;
+
///
/// 3812
///
diff --git a/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/HuddleVTCPanelAvFunctionsDriver.cs b/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/HuddleVTCPanelAvFunctionsDriver.cs
index cb05d1b5..1ce8663d 100644
--- a/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/HuddleVTCPanelAvFunctionsDriver.cs
+++ b/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/HuddleVTCPanelAvFunctionsDriver.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Collections.Generic;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
@@ -127,7 +128,7 @@ namespace PepperDash.Essentials
JoinedSigInterlock CallPagesInterlock;
- PepperDash.Essentials.UIDrivers.VC.EssentialsCiscoSparkUiDriver VCDriver;
+ PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver VCDriver;
///
/// Constructor
@@ -138,8 +139,6 @@ namespace PepperDash.Essentials
Config = config;
Parent = parent;
- VCDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsCiscoSparkUiDriver(Parent.TriList, null);
-
PopupInterlock = new JoinedSigInterlock(TriList);
StagingBarInterlock = new JoinedSigInterlock(TriList);
CallPagesInterlock = new JoinedSigInterlock(TriList);
@@ -158,6 +157,15 @@ namespace PepperDash.Essentials
//TriList.StringInput[UIStringJoin.StartActivityText].StringValue = "Tap an activity below";
}
+ ///
+ /// Add a video codec driver to this
+ ///
+ ///
+ public void SetVideoCodecDriver(PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver vcd)
+ {
+ VCDriver = vcd;
+ }
+
///
///
///
diff --git a/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsCiscoSparkUiDriver.cs b/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs
similarity index 90%
rename from Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsCiscoSparkUiDriver.cs
rename to Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs
index b61f39f6..00a402db 100644
--- a/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsCiscoSparkUiDriver.cs
+++ b/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs
@@ -19,8 +19,11 @@ namespace PepperDash.Essentials.UIDrivers.VC
/// Probably needs event or FB to feed AV driver - to show two-mute volume when appropriate.
///
///
- public class EssentialsCiscoSparkUiDriver : PanelDriverBase
+ public class EssentialsVideoCodecUiDriver : PanelDriverBase
{
+ ///
+ ///
+ ///
VideoCodecBase Codec;
///
@@ -62,7 +65,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
///
///
///
- public EssentialsCiscoSparkUiDriver(BasicTriListWithSmartObject triList, VideoCodecBase codec)
+ public EssentialsVideoCodecUiDriver(BasicTriListWithSmartObject triList, VideoCodecBase codec)
: base(triList)
{
Codec = codec;
@@ -146,6 +149,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
DialKeypad.Misc1.SetSigFalseAction(() => DialKeypadPress("*"));
DialKeypad.Misc2SigName = "#";
DialKeypad.Misc2.SetSigFalseAction(() => DialKeypadPress("#"));
+ TriList.SetSigFalseAction(UIBoolJoin.KeyboardClearPress, DialKeypadBackspacePress);
}
else
Debug.Console(0, "Trilist {0:x2}, VC dial keypad object {1} not found. Check SGD file or VTP",
@@ -198,6 +202,13 @@ namespace PepperDash.Essentials.UIDrivers.VC
void InCallFeedback_OutputChange(object sender, EventArgs e)
{
+#warning mode does not change!
+ var inCall = Codec.InCallFeedback.BoolValue;
+ Debug.Console(2, "*#* Codec Driver InCallFeedback change={0}", InCall);
+ TriList.UShortInput[UIUshortJoin.VCStagingConnectButtonMode].UShortValue = (ushort)(inCall ? 1 : 0);
+ StagingBarInterlock.ShowInterlocked(
+ inCall ? UIBoolJoin.VCStagingActivePopoverVisible : UIBoolJoin.VCStagingInactivePopoverVisible);
+
if (Codec.InCallFeedback.BoolValue) // Call is starting
{
// Header icon
@@ -224,12 +235,16 @@ namespace PepperDash.Essentials.UIDrivers.VC
DialStringBuilder.Length > 0;
}
+ ///
+ ///
+ ///
void DialKeypadBackspacePress()
{
DialStringBuilder.Remove(DialStringBuilder.Length - 1, 1);
DialStringFeedback.FireUpdate();
TriList.BooleanInput[UIBoolJoin.KeyboardClearVisible].BoolValue =
DialStringBuilder.Length > 0;
+ TriList.SetBool(UIBoolJoin.VCStagingConnectEnable, DialStringBuilder.Length > 0);
}
}
}
\ No newline at end of file
diff --git a/Release Package/PepperDashEssentials.cpz b/Release Package/PepperDashEssentials.cpz
index 7451c8ca..2232a636 100644
Binary files a/Release Package/PepperDashEssentials.cpz and b/Release Package/PepperDashEssentials.cpz differ
diff --git a/Release Package/PepperDashEssentials.dll b/Release Package/PepperDashEssentials.dll
index 679cdf05..678cd450 100644
Binary files a/Release Package/PepperDashEssentials.dll and b/Release Package/PepperDashEssentials.dll differ