diff --git a/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs b/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs index 7e6708da..bffea411 100644 --- a/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs +++ b/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs @@ -1,157 +1,167 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DM; -using Crestron.SimplSharpPro.DM.Endpoints; -using Crestron.SimplSharpPro.DM.Endpoints.Transmitters; - -using PepperDash.Core; -using PepperDash.Essentials.Core.Routing; - - -namespace PepperDash.Essentials.Core -{ - /// - /// - /// - public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback - - { - public RoutingInputPort HdmiIn1 { get; private set; } - public RoutingInputPort HdmiIn2 { get; private set; } - public RoutingInputPort HdmiIn3 { get; private set; } - public RoutingInputPort ComponentIn1 { get; private set; } - public RoutingInputPort VgaIn1 { get; private set; } - - bool _PowerIsOn; - bool _IsWarmingUp; - bool _IsCoolingDown; - - protected override Func PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } } - protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } } - protected override Func IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } } - - ushort _FakeVolumeLevel = 31768; - bool _IsMuted; - - public MockDisplay(string key, string name) - : base(key, name) - { - HdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.Hdmi, null, this); - HdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.Hdmi, null, this); - HdmiIn3 = new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.Hdmi, null, this); - ComponentIn1 = new RoutingInputPort(RoutingPortNames.ComponentIn, eRoutingSignalType.Video, - eRoutingPortConnectionType.Component, null, this); - VgaIn1 = new RoutingInputPort(RoutingPortNames.VgaIn, eRoutingSignalType.Video, - eRoutingPortConnectionType.Composite, null, this); - InputPorts.AddRange(new[] { HdmiIn1, HdmiIn2, HdmiIn3, ComponentIn1, VgaIn1 }); - - VolumeLevelFeedback = new IntFeedback(() => { return _FakeVolumeLevel; }); - MuteFeedback = new BoolFeedback(CommonBoolCue.MuteOn, () => _IsMuted); - } - - public override void PowerOn() - { - if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) - { - _IsWarmingUp = true; - IsWarmingUpFeedback.FireUpdate(); - // Fake power-up cycle - WarmupTimer = new CTimer(o => - { - _IsWarmingUp = false; - _PowerIsOn = true; - IsWarmingUpFeedback.FireUpdate(); - PowerIsOnFeedback.FireUpdate(); - }, WarmupTime); - } - } - - public override void PowerOff() - { - // If a display has unreliable-power off feedback, just override this and - // remove this check. - if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) - { - _IsCoolingDown = true; - _PowerIsOn = false; - PowerIsOnFeedback.FireUpdate(); - IsCoolingDownFeedback.FireUpdate(); - // Fake cool-down cycle - CooldownTimer = new CTimer(o => - { - Debug.Console(2, this, "Cooldown timer ending"); - _IsCoolingDown = false; - IsCoolingDownFeedback.FireUpdate(); - }, CooldownTime); - } - } - - public override void PowerToggle() - { - if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue) - PowerOff(); - else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue) - PowerOn(); - } - - public override void ExecuteSwitch(object selector) - { - Debug.Console(2, this, "ExecuteSwitch: {0}", selector); - } - - - - #region IBasicVolumeWithFeedback Members - - public IntFeedback VolumeLevelFeedback { get; private set; } - - public void SetVolume(ushort level) - { - _FakeVolumeLevel = level; - VolumeLevelFeedback.FireUpdate(); - } - - public void MuteOn() - { - _IsMuted = true; - MuteFeedback.FireUpdate(); - } - - public void MuteOff() - { - _IsMuted = false; - MuteFeedback.FireUpdate(); - } - - public BoolFeedback MuteFeedback { get; private set; } - - #endregion - - #region IBasicVolumeControls Members - - public void VolumeUp(bool pressRelease) - { - Debug.Console(0, this, "Volume Down {0}", pressRelease); - } - - public void VolumeDown(bool pressRelease) - { - Debug.Console(0, this, "Volume Up {0}", pressRelease); - } - - public void MuteToggle() - { - _IsMuted = !_IsMuted; - MuteFeedback.FireUpdate(); - } - - #endregion - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DM; +using Crestron.SimplSharpPro.DM.Endpoints; +using Crestron.SimplSharpPro.DM.Endpoints.Transmitters; + +using PepperDash.Core; +using PepperDash.Essentials.Core.Routing; + + +namespace PepperDash.Essentials.Core +{ + /// + /// + /// + public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback + + { + public RoutingInputPort HdmiIn1 { get; private set; } + public RoutingInputPort HdmiIn2 { get; private set; } + public RoutingInputPort HdmiIn3 { get; private set; } + public RoutingInputPort ComponentIn1 { get; private set; } + public RoutingInputPort VgaIn1 { get; private set; } + + bool _PowerIsOn; + bool _IsWarmingUp; + bool _IsCoolingDown; + + protected override Func PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } } + protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } } + protected override Func IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } } + + ushort _FakeVolumeLevel = 31768; + bool _IsMuted; + + public MockDisplay(string key, string name) + : base(key, name) + { + HdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, null, this); + HdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, null, this); + HdmiIn3 = new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, null, this); + ComponentIn1 = new RoutingInputPort(RoutingPortNames.ComponentIn, eRoutingSignalType.Video, + eRoutingPortConnectionType.Component, null, this); + VgaIn1 = new RoutingInputPort(RoutingPortNames.VgaIn, eRoutingSignalType.Video, + eRoutingPortConnectionType.Composite, null, this); + InputPorts.AddRange(new[] { HdmiIn1, HdmiIn2, HdmiIn3, ComponentIn1, VgaIn1 }); + + VolumeLevelFeedback = new IntFeedback(() => { return _FakeVolumeLevel; }); + MuteFeedback = new BoolFeedback(CommonBoolCue.MuteOn, () => _IsMuted); + } + + public override void PowerOn() + { + if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) + { + _IsWarmingUp = true; + IsWarmingUpFeedback.FireUpdate(); + // Fake power-up cycle + WarmupTimer = new CTimer(o => + { + _IsWarmingUp = false; + _PowerIsOn = true; + IsWarmingUpFeedback.FireUpdate(); + PowerIsOnFeedback.FireUpdate(); + }, WarmupTime); + } + } + + public override void PowerOff() + { + // If a display has unreliable-power off feedback, just override this and + // remove this check. + if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) + { + _IsCoolingDown = true; + _PowerIsOn = false; + PowerIsOnFeedback.FireUpdate(); + IsCoolingDownFeedback.FireUpdate(); + // Fake cool-down cycle + CooldownTimer = new CTimer(o => + { + Debug.Console(2, this, "Cooldown timer ending"); + _IsCoolingDown = false; + IsCoolingDownFeedback.FireUpdate(); + }, CooldownTime); + } + } + + public override void PowerToggle() + { + if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue) + PowerOff(); + else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue) + PowerOn(); + } + + public override void ExecuteSwitch(object selector) + { + Debug.Console(2, this, "ExecuteSwitch: {0}", selector); + } + + + + #region IBasicVolumeWithFeedback Members + + public IntFeedback VolumeLevelFeedback { get; private set; } + + public void SetVolume(ushort level) + { + _FakeVolumeLevel = level; + VolumeLevelFeedback.FireUpdate(); + } + + public void MuteOn() + { + _IsMuted = true; + MuteFeedback.FireUpdate(); + } + + public void MuteOff() + { + _IsMuted = false; + MuteFeedback.FireUpdate(); + } + + public BoolFeedback MuteFeedback { get; private set; } + + #endregion + + #region IBasicVolumeControls Members + + public void VolumeUp(bool pressRelease) + { + Debug.Console(2, this, "Volume Down {0}", pressRelease); + if (pressRelease) + { + var newLevel = _FakeVolumeLevel + 655; + SetVolume((ushort)newLevel); + } + } + + public void VolumeDown(bool pressRelease) + { + Debug.Console(2, this, "Volume Up {0}", pressRelease); + if (pressRelease) + { + var newLevel = _FakeVolumeLevel - 655; + SetVolume((ushort)newLevel); + } + } + + public void MuteToggle() + { + _IsMuted = !_IsMuted; + MuteFeedback.FireUpdate(); + } + + #endregion + } } \ No newline at end of file diff --git a/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo b/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo index aedc307d..9fdf18f4 100644 Binary files a/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo and b/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo differ diff --git a/Essentials DM/Essentials_DM/Essentials_DM.projectinfo b/Essentials DM/Essentials_DM/Essentials_DM.projectinfo index 0c8e39d2..3811ad6a 100644 Binary files a/Essentials DM/Essentials_DM/Essentials_DM.projectinfo and b/Essentials DM/Essentials_DM/Essentials_DM.projectinfo differ diff --git a/Essentials Devices Common/Essentials Devices Common/Display/NECPSXMDisplay.cs b/Essentials Devices Common/Essentials Devices Common/Display/NECPSXMDisplay.cs index e699563c..bdf2fdf7 100644 --- a/Essentials Devices Common/Essentials Devices Common/Display/NECPSXMDisplay.cs +++ b/Essentials Devices Common/Essentials Devices Common/Display/NECPSXMDisplay.cs @@ -338,15 +338,15 @@ namespace PepperDash.Essentials.Devices.Displays public void VolumeDown(bool pressRelease) { - throw new NotImplementedException(); -#warning need incrementer for these - //Send(VolumeDownCmd); + //throw new NotImplementedException(); +//#warning need incrementer for these + SetVolume(_VolumeLevel++); } public void VolumeUp(bool pressRelease) { - throw new NotImplementedException(); - //Send(VolumeUpCmd); + //throw new NotImplementedException(); + SetVolume(_VolumeLevel--); } #endregion diff --git a/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo b/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo index 814b9dc6..f4662abf 100644 Binary files a/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo and b/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo differ diff --git a/Essentials/PepperDashEssentials/Config/DeviceFactory.cs b/Essentials/PepperDashEssentials/Config/DeviceFactory.cs index 0a3bc4f6..d87e41b7 100644 --- a/Essentials/PepperDashEssentials/Config/DeviceFactory.cs +++ b/Essentials/PepperDashEssentials/Config/DeviceFactory.cs @@ -1,68 +1,73 @@ -using System; -using System.Collections.Generic; -using Crestron.SimplSharp; -using Crestron.SimplSharp.CrestronIO; -using Crestron.SimplSharpPro; - -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Config; - -namespace PepperDash.Essentials -{ - public class DeviceFactory - { - public static IKeyed GetDevice(DeviceConfig dc) - { - var key = dc.Key; - var name = dc.Name; - var type = dc.Type; - var properties = dc.Properties; - - var typeName = dc.Type.ToLower(); - - if (typeName == "amplifier") - { - return new Amplifier(dc.Key, dc.Name); - } - else if (dc.Group.ToLower() == "touchpanel") // typeName.StartsWith("tsw")) - { - var comm = CommFactory.GetControlPropertiesConfig(dc); - - var props = JsonConvert.DeserializeObject( - properties.ToString()); - return new EssentialsTouchpanelController(key, name, typeName, props, comm.IpIdInt); - } - else if (typeName == "mockdisplay") - { - return new MockDisplay(key, name); - } - - // MOVE into something else??? - else if (typeName == "basicirdisplay") - { - var ir = IRPortHelper.GetIrPort(properties); - if (ir != null) - return new BasicIrDisplay(key, name, ir.Port, ir.FileName); - } - - else if (typeName == "commmock") - { - var comm = CommFactory.CreateCommForDevice(dc); - var props = JsonConvert.DeserializeObject( - properties.ToString()); - return new ConsoleCommMockDevice(key, name, props, comm); +using System; +using System.Collections.Generic; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronIO; +using Crestron.SimplSharpPro; + +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; + +namespace PepperDash.Essentials +{ + public class DeviceFactory + { + public static IKeyed GetDevice(DeviceConfig dc) + { + var key = dc.Key; + var name = dc.Name; + var type = dc.Type; + var properties = dc.Properties; + + var typeName = dc.Type.ToLower(); + + if (typeName == "amplifier") + { + return new Amplifier(dc.Key, dc.Name); + } + else if (dc.Group.ToLower() == "touchpanel") // typeName.StartsWith("tsw")) + { + var comm = CommFactory.GetControlPropertiesConfig(dc); + + var props = JsonConvert.DeserializeObject( + properties.ToString()); + return new EssentialsTouchpanelController(key, name, typeName, props, comm.IpIdInt); + } + else if (typeName == "mockdisplay") + { + return new MockDisplay(key, name); + } + + else if (typeName == "generic") + { + return new Device(key, name); + } + + // MOVE into something else??? + else if (typeName == "basicirdisplay") + { + var ir = IRPortHelper.GetIrPort(properties); + if (ir != null) + return new BasicIrDisplay(key, name, ir.Port, ir.FileName); + } + + else if (typeName == "commmock") + { + var comm = CommFactory.CreateCommForDevice(dc); + var props = JsonConvert.DeserializeObject( + properties.ToString()); + return new ConsoleCommMockDevice(key, name, props, comm); } else if (typeName == "webserver") { var props = JsonConvert.DeserializeObject(properties.ToString()); return new CotijaSystemController(key, name, props); - } - - return null; - } - } -} + } + + return null; + } + } +} diff --git a/Essentials/PepperDashEssentials/ControlSystem.cs b/Essentials/PepperDashEssentials/ControlSystem.cs index 4a270d62..6cba22e5 100644 --- a/Essentials/PepperDashEssentials/ControlSystem.cs +++ b/Essentials/PepperDashEssentials/ControlSystem.cs @@ -162,6 +162,8 @@ namespace PepperDash.Essentials { if (room is EssentialsHuddleSpaceRoom) { + DeviceManager.AddDevice(room); + Debug.Console(1, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion"); DeviceManager.AddDevice(new EssentialsHuddleSpaceFusionSystemController((EssentialsHuddleSpaceRoom)room, 0xf1)); diff --git a/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo b/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo index b9a1020b..a3945a8e 100644 Binary files a/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo and b/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo differ diff --git a/Essentials/PepperDashEssentials/Room/Cotija/CotijaRoomBridge.cs b/Essentials/PepperDashEssentials/Room/Cotija/CotijaRoomBridge.cs new file mode 100644 index 00000000..570216f4 --- /dev/null +++ b/Essentials/PepperDashEssentials/Room/Cotija/CotijaRoomBridge.cs @@ -0,0 +1,226 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials +{ + public class CotijaEssentialsHuddleSpaceRoomBridge + { + CotijaSystemController Parent; + + public EssentialsHuddleSpaceRoom Room { get; private set; } + + public CotijaEssentialsHuddleSpaceRoomBridge(CotijaSystemController parent, EssentialsHuddleSpaceRoom room) + { + Parent = parent; + Room = room; + + // Source Changes and room off + Parent.AddAction(string.Format(@"/room/{0}/status",Room.Key), new Action(() => Room_RoomFullStatus(Room))); + Parent.AddAction(string.Format(@"/room/{0}/source", Room.Key), new Action(c => room.RunRouteAction(c.SourceSelect))); + Parent.AddAction(string.Format(@"/room/{0}/event/masterVolumeUpBtn", Room.Key), new Action(b => room.CurrentVolumeControls.VolumeUp(b))); + Parent.AddAction(string.Format(@"/room/{0}/event/masterVolumeDownBtn", Room.Key), new Action(b => room.CurrentVolumeControls.VolumeDown(b))); + Parent.AddAction(string.Format(@"/room/{0}/event/muteToggle", Room.Key), new Action(() => room.CurrentVolumeControls.MuteToggle())); + + Room.CurrentSingleSourceChange += new SourceInfoChangeHandler(Room_CurrentSingleSourceChange); + + Room.CurrentVolumeDeviceChange += new EventHandler(Room_CurrentVolumeDeviceChange); + + Room.OnFeedback.OutputChange += new EventHandler(OnFeedback_OutputChange); + + // Registers for initial volume events, if possible + var currentVolumeDevice = Room.CurrentVolumeControls; + + if (currentVolumeDevice != null) + { + if (currentVolumeDevice is IBasicVolumeWithFeedback) + { + var newDev = currentVolumeDevice as IBasicVolumeWithFeedback; + + newDev.MuteFeedback.OutputChange += new EventHandler(VolumeLevelFeedback_OutputChange); + newDev.VolumeLevelFeedback.OutputChange += new EventHandler(VolumeLevelFeedback_OutputChange); + } + } + + } + + void OnFeedback_OutputChange(object sender, EventArgs e) + { + /* Example message + * { + "type":"/room/status", + "content": { + "isOn": false + } + } + */ + + JObject roomStatus = new JObject(); + + roomStatus.Add("isOn", (sender as BoolFeedback).BoolValue); + + JObject message = new JObject(); + + message.Add("type", "/room/status/"); + message.Add("content", roomStatus); + + Parent.PostToServer(Room, message); + } + + void Room_CurrentVolumeDeviceChange(object sender, VolumeDeviceChangeEventArgs e) + { + if (e.OldDev is IBasicVolumeWithFeedback) + { + var oldDev = e.OldDev as IBasicVolumeWithFeedback; + + oldDev.MuteFeedback.OutputChange -= VolumeLevelFeedback_OutputChange; + oldDev.VolumeLevelFeedback.OutputChange -= VolumeLevelFeedback_OutputChange; + } + + if (e.NewDev is IBasicVolumeWithFeedback) + { + var newDev = e.NewDev as IBasicVolumeWithFeedback; + + newDev.MuteFeedback.OutputChange += new EventHandler(VolumeLevelFeedback_OutputChange); + newDev.VolumeLevelFeedback.OutputChange += new EventHandler(VolumeLevelFeedback_OutputChange); + } + } + + void VolumeLevelFeedback_OutputChange(object sender, EventArgs e) + { + /* Example message + * { +   "type":"/room/status", +   "content": { +     "masterVolumeLevel": 12345, +     "masterVolumeMuteState": false +   } + } + */ + + var huddleRoom = Room as EssentialsHuddleSpaceRoom; + + if(huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback) + { + JObject roomStatus = new JObject(); + + if (huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback) + { + var currentVolumeConstrols = huddleRoom.CurrentVolumeControls as IBasicVolumeWithFeedback; + roomStatus.Add("masterVolumeLevel", currentVolumeConstrols.VolumeLevelFeedback.IntValue); + roomStatus.Add("masterVolumeMuteState", currentVolumeConstrols.MuteFeedback.BoolValue); + } + + JObject message = new JObject(); + + message.Add("type", "/room/status/"); + message.Add("content", roomStatus); + + Parent.PostToServer(Room, message); + } + } + + void Room_CurrentSingleSourceChange(EssentialsRoomBase room, PepperDash.Essentials.Core.SourceListItem info, ChangeType type) + { + /* Example message + * { +   "type":"/room/status", +   "content": { +     "selectedSourceKey": "off", +   } + } + */ + + if (type != ChangeType.DidChange) + return; + + JObject roomStatus = new JObject(); + + var huddleRoom = room as EssentialsHuddleSpaceRoom; + //roomStatus.Add("isOn", huddleRoom.OnFeedback.BoolValue); + roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey); + + JObject message = new JObject(); + + message.Add("type", "/room/status/"); + message.Add("content", roomStatus); + + Parent.PostToServer(Room, message); + } + + /// + /// Posts the full status of the room to the server + /// + /// + void Room_RoomFullStatus(EssentialsRoomBase room) + { + /* Example message + * { + "type":"/room/status", + "content": { + "selectedSourceKey": "off", + "isOn": false, + "masterVolumeLevel": 50, + "masterVolumeMuteState": false + } + } + */ + + JObject roomStatus = new JObject(); + + var huddleRoom = room as EssentialsHuddleSpaceRoom; + roomStatus.Add("isOn", huddleRoom.OnFeedback.BoolValue); + roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey); + + + if(huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback) + { + var currentVolumeConstrols = huddleRoom.CurrentVolumeControls as IBasicVolumeWithFeedback; + roomStatus.Add("masterVolumeLevel", currentVolumeConstrols.VolumeLevelFeedback.IntValue); + roomStatus.Add("masterVolumeMuteState", currentVolumeConstrols.MuteFeedback.BoolValue); + } + + JObject message = new JObject(); + + message.Add("type", "/room/status/"); + message.Add("content", roomStatus); + + Parent.PostToServer(Room, message); + + } + + } + + public class SourceSelectMessageContent + { + public string Destination { get; set; } + public string SourceSelect { get; set; } + } + + //public class PostMessage + //{ + // [JsonProperty("type")] + // public string Type { get; set; } + + // [JsonProperty("content")] + // public JToken Content { get; set; } + //} + + //public class RoomStatusMessageContent + //{ + // [JsonProperty("selectedSourceKey")] + // public string SelectedSourceKey { get; set; } + // [JsonProperty("isOn")] + // public bool? IsOn { get; set; } + // [JsonProperty("masterVolumeLevel")] + // public int? MasterVolumeLevel { get; set; } + // [JsonProperty("masterVolumeMuteState")] + // public bool? MasterVolumeMuteState { get; set; } + //} + +} \ No newline at end of file diff --git a/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs b/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs index 7ac090f2..7ddffbd6 100644 --- a/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs +++ b/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs @@ -42,18 +42,33 @@ namespace PepperDash.Essentials CotijaRooms = new List(); - CrestronConsole.AddNewConsoleCommand(ConnectSseClient, "InitializeHttpClient", "Initializes a new HTTP client connection to a specified URL", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(RegisterSystemToServer, "InitializeHttpClient", "Initializes a new HTTP client connection to a specified URL", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(DisconnectSseClient, "CloseHttpClient", "Closes the active HTTP client", ConsoleAccessLevelEnum.AccessOperator); AddPostActivationAction(() => RegisterSystemToServer(null)); } + /// + /// Adds an action to the dictionary + /// + /// The path of the API command + /// The action to be triggered by the commmand public void AddAction(string key, object action) { - // This might blow up if an action with that key already exists - ActionDictionary.Add(key, action); + if (!ActionDictionary.ContainsKey(key)) + { + ActionDictionary.Add(key, action); + } + else + { + Debug.Console(1, this, "Cannot add action with key '{0}' because key already exists in ActionDictionary."); + } } + /// + /// Removes and action from the dictionary + /// + /// public void RemoveAction(string key) { if (ActionDictionary.ContainsKey(key)) @@ -135,22 +150,39 @@ namespace PepperDash.Essentials /// object to be serialized and sent in post body public void PostToServer(EssentialsRoomBase room, JObject o) { - if(Client == null) - Client = new HttpClient(); + try + { + if (Client == null) + Client = new HttpClient(); - HttpClientRequest request = new HttpClientRequest(); + //HttpClient client = new HttpClient(); - Client.Verbose = true; - Client.KeepAlive = true; + HttpClientRequest request = new HttpClientRequest(); - string url = string.Format("http://{0}/api/room/{1}", Config.serverUrl, string.Format("{0}-{1}", SystemUuid, room.Key)); + Client.Verbose = true; + Client.KeepAlive = true; - request.Url.Parse(url); - request.RequestType = RequestType.Post; - request.Header.SetHeaderValue("Content-Type", "application/json"); - request.ContentString = o.ToString(); + string url = string.Format("http://{0}/api/room/{1}/status", Config.serverUrl, string.Format("{0}--{1}", SystemUuid, room.Key)); - Client.DispatchAsync(request, PostConnectionCallback); + request.Url.Parse(url); + request.RequestType = RequestType.Post; + request.Header.SetHeaderValue("Content-Type", "application/json"); + request.KeepAlive = true; + + // Ignore any null objects when serializing and remove formatting + string ignored = JsonConvert.SerializeObject(o, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); + request.ContentString = ignored; + + Debug.Console(1, this, "Posting to '{0}':\n{1}", url, request.ContentString); + + Client.DispatchAsync(request, (r, err) => { if (r != null) { Debug.Console(1, this, "Status Response Code: {0}", r.Code); } }); + + StartReconnectTimer(5000, 5000); + } + catch(Exception e) + { + Debug.Console(1, this, "Error Posting to Server: {0}", e); + } } /// @@ -181,6 +213,13 @@ namespace PepperDash.Essentials { if (resp != null && resp.Code == 200) { + if(Reconnect != null) + { + Reconnect.Stop(); + + Reconnect = null; + } + if (SseClient == null) { ConnectSseClient(null); @@ -188,12 +227,12 @@ namespace PepperDash.Essentials } else { - Debug.Console(0, this, "Unable to initialize SSE Client"); + Debug.Console(0, this, "Response from server: {0}\n{1}", resp.Code, err); } } catch (Exception e) { - Debug.Console(1, this, "Error Initializeing SSE Client: {0}", e); + Debug.Console(1, this, "Error Initializing SSE Client: {0}", e); } } @@ -205,15 +244,22 @@ namespace PepperDash.Essentials { if (Heartbeat != null) { + Debug.Console(1, this, "Heartbeat Timer Expired."); + Heartbeat.Stop(); Heartbeat = null; } - // Start the reconnect timer - Reconnect = new CTimer(ReconnectToServer, null, 5000, 5000); + StartReconnectTimer(5000, 5000); + } - Reconnect.Reset(5000, 5000); + void StartReconnectTimer(long dueTime, long repeatTime) + { + // Start the reconnect timer + Reconnect = new CTimer(ReconnectToServer, null, dueTime, repeatTime); + + Reconnect.Reset(dueTime, repeatTime); } @@ -246,11 +292,8 @@ namespace PepperDash.Essentials SseClient.Url = string.Format("http://{0}/api/system/stream/{1}", Config.serverUrl, uuid); SseClient.Connect(); - - //Heartbeat = new CTimer(HeartbeatExpired, null, 20000, 20000); - - //Heartbeat.Reset(20000, 20000); } + void LineGathered_LineReceived(object sender, GenericCommMethodReceiveTextArgs e) { @@ -260,8 +303,6 @@ namespace PepperDash.Essentials { var message = e.Text.Substring(6); - string roomId = null; - Debug.Console(1, this, "Message: '{0}'", message); try @@ -270,11 +311,21 @@ namespace PepperDash.Essentials var type = messageObj["type"].Value(); - if(type == "/system/hearbeat") + if (type == "hello") { - //Heartbeat.Reset(20000, 20000); + Heartbeat = new CTimer(HeartbeatExpired, null, 20000, 20000); + + Debug.Console(2, this, "Heartbeat Timer Started."); + + Heartbeat.Reset(20000, 20000); } - else if(type == "close") + else if (type == "/system/heartbeat") + { + Heartbeat.Reset(20000, 20000); + + Debug.Console(2, this, "Heartbeat Timer Reset."); + } + else if (type == "close") { SseClient.Disconnect(); @@ -285,19 +336,21 @@ namespace PepperDash.Essentials } else { - - // Check path against Action dictionary if (ActionDictionary.ContainsKey(type)) { var action = ActionDictionary[type]; - if (action is Action) + if (action is Action) + { + (action as Action)(); + } + else if (action is Action) { var stateString = messageObj["content"]["state"].Value(); // Look for a button press event - if(!string.IsNullOrEmpty(stateString)) + if (!string.IsNullOrEmpty(stateString)) { #warning deal with held state later if (stateString == "held") @@ -320,7 +373,7 @@ namespace PepperDash.Essentials .ToObject()); } } - + } } diff --git a/Essentials/PepperDashEssentials/Room/EssentialsHuddleSpaceRoom.cs b/Essentials/PepperDashEssentials/Room/EssentialsHuddleSpaceRoom.cs index 9485ee10..fa7bee4c 100644 --- a/Essentials/PepperDashEssentials/Room/EssentialsHuddleSpaceRoom.cs +++ b/Essentials/PepperDashEssentials/Room/EssentialsHuddleSpaceRoom.cs @@ -80,14 +80,16 @@ namespace PepperDash.Essentials _CurrentSourceInfo = value; - // add to in-use tracking + // add to in-use tracking if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking) (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control"); if (handler != null) handler(this, _CurrentSourceInfo, ChangeType.DidChange); } } - SourceListItem _CurrentSourceInfo; + SourceListItem _CurrentSourceInfo; + + public string CurrentSourceInfoKey { get; private set; } /// /// @@ -154,9 +156,15 @@ namespace PepperDash.Essentials Debug.Console(2, this, "Action {0} has {1} steps", item.SourceKey, item.RouteList.Count); - // Let's run it - if (routeKey.ToLower() != "roomoff") - LastSourceKey = routeKey; + // Let's run it + if (routeKey.ToLower() != "roomoff") + { + LastSourceKey = routeKey; + } + else + { + CurrentSourceInfoKey = null; + } foreach (var route in item.RouteList) { @@ -203,9 +211,12 @@ namespace PepperDash.Essentials } CurrentVolumeControls = volDev; - // store the name and UI info for routes - if (item.SourceKey != null) - CurrentSourceInfo = item; + // store the name and UI info for routes + if (item.SourceKey != null) + { + CurrentSourceInfoKey = routeKey; + CurrentSourceInfo = item; + } // And finally, set the "control". This will trigger event //CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device; diff --git a/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs index 17321bb3..a6b1f623 100644 --- a/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs +++ b/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs @@ -94,7 +94,7 @@ namespace PepperDash.Essentials var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, props); // Then the AV driver - // spin up different room drivers depending on room type + // spin up different room drivers depending on room type var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey); if (room is EssentialsHuddleSpaceRoom) {