diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsDualDisplayRoomPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsDualDisplayRoomPropertiesConfig.cs
new file mode 100644
index 00000000..3b3489bf
--- /dev/null
+++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsDualDisplayRoomPropertiesConfig.cs
@@ -0,0 +1,8 @@
+
+namespace PDT.Plugins.Essentials.Rooms.Config
+{
+ public class EssentialsDualDisplayRoomPropertiesConfig : EssentialsNDisplayRoomPropertiesConfig
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleRoomPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleRoomPropertiesConfig.cs
new file mode 100644
index 00000000..76a35689
--- /dev/null
+++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleRoomPropertiesConfig.cs
@@ -0,0 +1,34 @@
+using Newtonsoft.Json;
+
+namespace PDT.Plugins.Essentials.Rooms.Config
+{
+ ///
+ ///
+ ///
+ public class EssentialsHuddleRoomPropertiesConfig : EssentialsRoomPropertiesConfig
+ {
+ ///
+ /// The key of the default display device
+ ///
+ [JsonProperty("defaultDisplayKey")]
+ public string DefaultDisplayKey { get; set; }
+
+ ///
+ /// The key of the default audio device
+ ///
+ [JsonProperty("defaultAudioKey")]
+ public string DefaultAudioKey { get; set; }
+
+ ///
+ /// The key of the source list for the room
+ ///
+ [JsonProperty("sourceListKey")]
+ public string SourceListKey { get; set; }
+
+ ///
+ /// The key of the default source item from the source list
+ ///
+ [JsonProperty("defaultSourceItem")]
+ public string DefaultSourceItem { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs
new file mode 100644
index 00000000..0071d9ee
--- /dev/null
+++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs
@@ -0,0 +1,13 @@
+
+using Newtonsoft.Json;
+
+namespace PDT.Plugins.Essentials.Rooms.Config
+{
+
+ public class EssentialsHuddleVtc1PropertiesConfig : EssentialsConferenceRoomPropertiesConfig
+ {
+ [JsonProperty("defaultDisplayKey")]
+ public string DefaultDisplayKey { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsNDisplayRoomPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsNDisplayRoomPropertiesConfig.cs
new file mode 100644
index 00000000..7d4d2bc4
--- /dev/null
+++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsNDisplayRoomPropertiesConfig.cs
@@ -0,0 +1,34 @@
+
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+
+namespace PDT.Plugins.Essentials.Rooms.Config
+{
+ ///
+ ///
+ ///
+ public class EssentialsNDisplayRoomPropertiesConfig : EssentialsConferenceRoomPropertiesConfig
+ {
+ [JsonProperty("defaultAudioBehavior")]
+ public string DefaultAudioBehavior { get; set; }
+ [JsonProperty("defaultVideoBehavior")]
+ public string DefaultVideoBehavior { get; set; }
+ [JsonProperty("displays")]
+ public Dictionary Displays { get; set; }
+
+ public EssentialsNDisplayRoomPropertiesConfig()
+ {
+ Displays = new Dictionary();
+ }
+
+ }
+
+ public class DisplayItem : IKeyName
+ {
+ public string Key { get; set; }
+ public string Name { get; set; }
+ }
+
+}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsPresentationPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsPresentationPropertiesConfig.cs
new file mode 100644
index 00000000..125a818f
--- /dev/null
+++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsPresentationPropertiesConfig.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+
+namespace PDT.Plugins.Essentials.Rooms.Config
+{
+ ///
+ ///
+ ///
+ public class EssentialsPresentationRoomPropertiesConfig : EssentialsRoomPropertiesConfig
+ {
+ public string DefaultAudioBehavior { get; set; }
+ public string DefaultAudioKey { get; set; }
+ public string DefaultVideoBehavior { get; set; }
+ public List DisplayKeys { get; set; }
+ public string SourceListKey { get; set; }
+ public bool HasDsp { get; set; }
+
+ public EssentialsPresentationRoomPropertiesConfig()
+ {
+ DisplayKeys = new List();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs
new file mode 100644
index 00000000..ac5f7b10
--- /dev/null
+++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs
@@ -0,0 +1,406 @@
+using System;
+using System.Collections.Generic;
+using Crestron.SimplSharp;
+using Newtonsoft.Json;
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Core.Config;
+using PepperDash.Essentials.Core.Privacy;
+
+namespace PDT.Plugins.Essentials.Rooms.Config
+{
+ public class EssentialsRoomConfigHelper
+ {
+ ///
+ /// Returns a room object from this config data
+ ///
+ ///
+ public static IKeyed GetRoomObject(DeviceConfig roomConfig)
+ {
+ var typeName = roomConfig.Type.ToLower();
+
+ switch (typeName)
+ {
+ case "huddle" :
+ {
+ return new EssentialsHuddleSpaceRoom(roomConfig);
+ }
+ case "huddlevtc1" :
+ {
+ return new EssentialsHuddleVtc1Room(roomConfig);
+ }
+ case "ddvc01bridge" :
+ {
+ return new Device(roomConfig.Key, roomConfig.Name); // placeholder device that does nothing.
+ }
+ case "dualdisplay" :
+ {
+ return new EssentialsDualDisplayRoom(roomConfig);
+ }
+ case "combinedhuddlevtc1" :
+ {
+ return new EssentialsCombinedHuddleVtc1Room(roomConfig);
+ }
+ case "techroom" :
+ {
+ return new EssentialsTechRoom(roomConfig);
+ }
+ default :
+ {
+ return DeviceFactory.GetDevice(roomConfig);
+ }
+ }
+ }
+
+ ///
+ /// Gets and operating, standalone emergegncy object that can be plugged into a room.
+ /// Returns null if there is no emergency defined
+ ///
+ public static EssentialsRoomEmergencyBase GetEmergency(EssentialsRoomPropertiesConfig props, IEssentialsRoom room)
+ {
+ // This emergency
+ var emergency = props.Emergency;
+ if (emergency != null)
+ {
+ //switch on emergency type here. Right now only contact and shutdown
+ var e = new EssentialsRoomEmergencyContactClosure(room.Key + "-emergency", props.Emergency, room);
+ DeviceManager.AddDevice(e);
+ }
+ return null;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static MicrophonePrivacyController GetMicrophonePrivacy(
+ EssentialsRoomPropertiesConfig props, IPrivacy room)
+ {
+ var microphonePrivacy = props.MicrophonePrivacy;
+ if (microphonePrivacy == null)
+ {
+ Debug.Console(0, "Cannot create microphone privacy with null properties");
+ return null;
+ }
+ // Get the MicrophonePrivacy device from the device manager
+ var mP = (DeviceManager.GetDeviceForKey(props.MicrophonePrivacy.DeviceKey) as MicrophonePrivacyController);
+ // Set this room as the IPrivacy device
+ if (mP == null)
+ {
+ Debug.Console(0, "ERROR: Selected device {0} is not MicrophonePrivacyController", props.MicrophonePrivacy.DeviceKey);
+ return null;
+ }
+ mP.SetPrivacyDevice(room);
+
+ var behaviour = props.MicrophonePrivacy.Behaviour.ToLower();
+
+ if (behaviour == null)
+ {
+ Debug.Console(0, "WARNING: No behaviour defined for MicrophonePrivacyController");
+ return null;
+ }
+ if (behaviour == "trackroomstate")
+ {
+ // Tie LED enable to room power state
+ var essRoom = room as IEssentialsRoom;
+ essRoom.OnFeedback.OutputChange += (o, a) =>
+ {
+ if (essRoom.OnFeedback.BoolValue)
+ mP.EnableLeds = true;
+ else
+ mP.EnableLeds = false;
+ };
+
+ mP.EnableLeds = essRoom.OnFeedback.BoolValue;
+ }
+ else if (behaviour == "trackcallstate")
+ {
+ // Tie LED enable to room power state
+ var inCallRoom = room as IHasInCallFeedback;
+ inCallRoom.InCallFeedback.OutputChange += (o, a) =>
+ {
+ if (inCallRoom.InCallFeedback.BoolValue)
+ mP.EnableLeds = true;
+ else
+ mP.EnableLeds = false;
+ };
+
+ mP.EnableLeds = inCallRoom.InCallFeedback.BoolValue;
+ }
+
+ return mP;
+ }
+
+ }
+
+ ///
+ ///
+ ///
+ public class EssentialsRoomPropertiesConfig
+ {
+ [JsonProperty("addresses")]
+ public EssentialsRoomAddressPropertiesConfig Addresses { get; set; }
+
+ [JsonProperty("description")]
+ public string Description { get; set; }
+
+ [JsonProperty("emergency")]
+ public EssentialsRoomEmergencyConfig Emergency { get; set; }
+
+ [JsonProperty("help")]
+ public EssentialsHelpPropertiesConfig Help { get; set; }
+
+ [JsonProperty("helpMessage")]
+ public string HelpMessage { get; set; }
+
+ ///
+ /// Read this value to get the help message. It checks for the old and new config format.
+ ///
+ public string HelpMessageForDisplay
+ {
+ get
+ {
+ if(Help != null && !string.IsNullOrEmpty(Help.Message))
+ {
+ return Help.Message;
+ }
+ else
+ {
+ return HelpMessage;
+ }
+ }
+ }
+
+ [JsonProperty("environment")]
+ public EssentialsEnvironmentPropertiesConfig Environment { get; set; }
+
+ [JsonProperty("logo")]
+ public EssentialsLogoPropertiesConfig LogoLight { get; set; }
+
+ [JsonProperty("logoDark")]
+ public EssentialsLogoPropertiesConfig LogoDark { get; set; }
+
+ [JsonProperty("microphonePrivacy")]
+ public EssentialsRoomMicrophonePrivacyConfig MicrophonePrivacy { get; set; }
+
+ [JsonProperty("occupancy")]
+ public EssentialsRoomOccSensorConfig Occupancy { get; set; }
+
+ [JsonProperty("oneButtonMeeting")]
+ public EssentialsOneButtonMeetingPropertiesConfig OneButtonMeeting { get; set; }
+
+ [JsonProperty("shutdownVacancySeconds")]
+ public int ShutdownVacancySeconds { get; set; }
+
+ [JsonProperty("shutdownPromptSeconds")]
+ public int ShutdownPromptSeconds { get; set; }
+
+ [JsonProperty("tech")]
+ public EssentialsRoomTechConfig Tech { get; set; }
+
+ [JsonProperty("volumes")]
+ public EssentialsRoomVolumesConfig Volumes { get; set; }
+
+ [JsonProperty("fusion")]
+ public EssentialsRoomFusionConfig Fusion { get; set; }
+
+ [JsonProperty("essentialsRoomUiBehaviorConfig", NullValueHandling=NullValueHandling.Ignore)]
+ public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; }
+
+ [JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
+ public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
+
+ ///
+ /// Indicates if this room represents a combination of other rooms
+ ///
+ [JsonProperty("isRoomCombinationScenario")]
+ public bool IsRoomCombinationScenario { get; set; }
+
+ public EssentialsRoomPropertiesConfig()
+ {
+ LogoLight = new EssentialsLogoPropertiesConfig();
+ LogoDark = new EssentialsLogoPropertiesConfig();
+ }
+ }
+
+ public class EssentialsRoomUiBehaviorConfig
+ {
+ [JsonProperty("disableActivityButtonsWhileWarmingCooling")]
+ public bool DisableActivityButtonsWhileWarmingCooling { get; set; }
+ }
+
+ public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig
+ {
+ [JsonProperty("defaultAudioKey")]
+ public string DefaultAudioKey { get; set; }
+ [JsonProperty("sourceListKey")]
+ public string SourceListKey { get; set; }
+ [JsonProperty("destinationListKey")]
+ public string DestinationListKey { get; set; }
+ [JsonProperty("defaultSourceItem")]
+ public string DefaultSourceItem { get; set; }
+ ///
+ /// Indicates if the room supports advanced sharing
+ ///
+ [JsonProperty("supportsAdvancedSharing")]
+ public bool SupportsAdvancedSharing { get; set; }
+ ///
+ /// Indicates if non-tech users can change the share mode
+ ///
+ [JsonProperty("userCanChangeShareMode")]
+ public bool UserCanChangeShareMode { get; set; }
+ }
+
+ public class EssentialsConferenceRoomPropertiesConfig : EssentialsAvRoomPropertiesConfig
+ {
+ [JsonProperty("videoCodecKey")]
+ public string VideoCodecKey { get; set; }
+ [JsonProperty("audioCodecKey")]
+ public string AudioCodecKey { get; set; }
+ }
+
+ public class EssentialsEnvironmentPropertiesConfig
+ {
+ public bool Enabled { get; set; }
+
+ [JsonProperty("deviceKeys")]
+ public List DeviceKeys { get; set; }
+
+ public EssentialsEnvironmentPropertiesConfig()
+ {
+ DeviceKeys = new List();
+ }
+
+ }
+
+ public class EssentialsRoomFusionConfig
+ {
+ public uint IpIdInt
+ {
+ get
+ {
+ try
+ {
+ return Convert.ToUInt32(IpId, 16);
+ }
+ catch (Exception)
+ {
+ throw new FormatException(string.Format("ERROR:Unable to convert IP ID: {0} to hex. Error:\n{1}", IpId));
+ }
+
+ }
+ }
+
+ [JsonProperty("ipId")]
+ public string IpId { get; set; }
+
+ [JsonProperty("joinMapKey")]
+ public string JoinMapKey { get; set; }
+
+ }
+
+ public class EssentialsRoomMicrophonePrivacyConfig
+ {
+ [JsonProperty("deviceKey")]
+ public string DeviceKey { get; set; }
+
+ [JsonProperty("behaviour")]
+ public string Behaviour { get; set; }
+ }
+
+ ///
+ /// Properties for the help text box
+ ///
+ public class EssentialsHelpPropertiesConfig
+ {
+ [JsonProperty("message")]
+ public string Message { get; set; }
+
+ [JsonProperty("showCallButton")]
+ public bool ShowCallButton { get; set; }
+
+ ///
+ /// Defaults to "Call Help Desk"
+ ///
+ [JsonProperty("callButtonText")]
+ public string CallButtonText { get; set; }
+
+ public EssentialsHelpPropertiesConfig()
+ {
+ CallButtonText = "Call Help Desk";
+ }
+ }
+
+ ///
+ ///
+ ///
+ public class EssentialsOneButtonMeetingPropertiesConfig
+ {
+ [JsonProperty("enable")]
+ public bool Enable { get; set; }
+ }
+
+ public class EssentialsRoomAddressPropertiesConfig
+ {
+ [JsonProperty("phoneNumber")]
+ public string PhoneNumber { get; set; }
+
+ [JsonProperty("sipAddress")]
+ public string SipAddress { get; set; }
+ }
+
+
+ ///
+ /// Properties for the room's logo on panels
+ ///
+ public class EssentialsLogoPropertiesConfig
+ {
+ [JsonProperty("type")]
+ public string Type { get; set; }
+
+ [JsonProperty("url")]
+ public string Url { get; set; }
+ ///
+ /// Gets either the custom URL, a local-to-processor URL, or null if it's a default logo
+ ///
+ public string GetLogoUrlLight()
+ {
+ if (Type == "url")
+ return Url;
+ if (Type == "system")
+ return string.Format("http://{0}:8080/logo.png",
+ CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0));
+ return null;
+ }
+
+ public string GetLogoUrlDark()
+ {
+ if (Type == "url")
+ return Url;
+ if (Type == "system")
+ return string.Format("http://{0}:8080/logo-dark.png",
+ CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0));
+ return null;
+ }
+ }
+
+ ///
+ /// Represents occupancy sensor(s) setup for a room
+ ///
+ public class EssentialsRoomOccSensorConfig
+ {
+ [JsonProperty("deviceKey")]
+ public string DeviceKey { get; set; }
+
+ [JsonProperty("timeoutMinutes")]
+ public int TimeoutMinutes { get; set; }
+ }
+
+ public class EssentialsRoomTechConfig
+ {
+ [JsonProperty("password")]
+ public string Password { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomEmergencyConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomEmergencyConfig.cs
new file mode 100644
index 00000000..0100f006
--- /dev/null
+++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomEmergencyConfig.cs
@@ -0,0 +1,30 @@
+namespace PDT.Plugins.Essentials.Rooms.Config
+{
+ ///
+ ///
+ ///
+ public class EssentialsRoomEmergencyConfig
+ {
+ public EssentialsRoomEmergencyTriggerConfig Trigger { get; set; }
+
+ public string Behavior { get; set; }
+ }
+
+ ///
+ ///
+ ///
+ public class EssentialsRoomEmergencyTriggerConfig
+ {
+ ///
+ /// contact,
+ ///
+ public string Type { get; set; }
+ ///
+ /// Input number if contact
+ ///
+ public int Number { get; set; }
+
+ public bool TriggerOnClose { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsTechRoomConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsTechRoomConfig.cs
new file mode 100644
index 00000000..1de4128d
--- /dev/null
+++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsTechRoomConfig.cs
@@ -0,0 +1,77 @@
+
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using PepperDash.Essentials.Room.Config;
+
+namespace PDT.Plugins.Essentials.Rooms.Config
+{
+ public class EssentialsTechRoomConfig
+ {
+ ///
+ /// The key of the dummy device used to enable routing
+ ///
+ [JsonProperty("dummySourceKey")]
+ public string DummySourceKey { get; set; }
+
+ ///
+ /// The keys of the displays assigned to this room
+ ///
+ [JsonProperty("displays")]
+ public List Displays { get; set; }
+
+ ///
+ /// The keys of the tuners assinged to this room
+ ///
+ [JsonProperty("tuners")]
+ public List Tuners { get; set; }
+
+ ///
+ /// PIN to access the room as a normal user
+ ///
+ [JsonProperty("userPin")]
+ public string UserPin { get; set; }
+
+ ///
+ /// PIN to access the room as a tech user
+ ///
+ [JsonProperty("techPin")]
+ public string TechPin { get; set; }
+
+ ///
+ /// Name of the presets file. Path prefix is assumed to be /html/presets/lists/
+ ///
+ [JsonProperty("presetsFileName")]
+ public string PresetsFileName { get; set; }
+
+ [JsonProperty("scheduledEvents")]
+ public List ScheduledEvents { get; set; }
+
+ ///
+ /// Indicates that the room is the primary when true
+ ///
+ [JsonProperty("isPrimary")]
+ public bool IsPrimary { get; set; }
+
+ ///
+ /// Indicates which tuners should mirror preset recall when two rooms are configured in a primary->secondary scenario
+ ///
+ [JsonProperty("mirroredTuners")]
+ public Dictionary MirroredTuners { get; set; }
+
+ [JsonProperty("helpMessage")]
+ public string HelpMessage { get; set; }
+
+ ///
+ /// Indicates the room
+ ///
+ [JsonProperty("isTvPresetsProvider")]
+ public bool IsTvPresetsProvider;
+
+ public EssentialsTechRoomConfig()
+ {
+ Displays = new List();
+ Tuners = new List();
+ ScheduledEvents = new List();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Room/Config/SimplRoomPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/SimplRoomPropertiesConfig.cs
new file mode 100644
index 00000000..52aac362
--- /dev/null
+++ b/src/PepperDash.Essentials.Core/Room/Config/SimplRoomPropertiesConfig.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace PDT.Plugins.Essentials.Rooms.Config
+{
+ public class SimplRoomPropertiesConfig : EssentialsHuddleVtc1PropertiesConfig
+ {
+ [JsonProperty("roomPhoneNumber")]
+ public string RoomPhoneNumber { get; set; }
+ [JsonProperty("roomURI")]
+ public string RoomURI { get; set; }
+ [JsonProperty("speedDials")]
+ public List SpeedDials { get; set; }
+ [JsonProperty("volumeSliderNames")]
+ public List VolumeSliderNames { get; set; }
+ }
+
+ public class SimplSpeedDial
+ {
+ [JsonProperty("name")]
+ public string Name { get; set; }
+ [JsonProperty("number")]
+ public string Number { get; set; }
+ }
+}
\ No newline at end of file