diff --git a/Essentials/PepperDashEssentials/Config/EssentialsConfig.cs b/Essentials/PepperDashEssentials/Config/EssentialsConfig.cs index 34d2f516..44f8fa8f 100644 --- a/Essentials/PepperDashEssentials/Config/EssentialsConfig.cs +++ b/Essentials/PepperDashEssentials/Config/EssentialsConfig.cs @@ -16,7 +16,10 @@ namespace PepperDash.Essentials /// public class EssentialsConfig : BasicConfig { + [JsonProperty("system_url")] public string SystemUrl { get; set; } + + [JsonProperty("template_url")] public string TemplateUrl { get; set; } public CotijaConfig Cotija { get; private set; } @@ -25,7 +28,7 @@ namespace PepperDash.Essentials { get { - var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/templates\/(.*)#.*"); + var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*"); string uuid = result.Groups[1].Value; @@ -37,7 +40,7 @@ namespace PepperDash.Essentials { get { - var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)#.*"); + var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)\/#.*"); string uuid = result.Groups[1].Value; diff --git a/Essentials/PepperDashEssentials/Properties/AssemblyInfo.cs b/Essentials/PepperDashEssentials/Properties/AssemblyInfo.cs index 80af5d68..5134564c 100644 --- a/Essentials/PepperDashEssentials/Properties/AssemblyInfo.cs +++ b/Essentials/PepperDashEssentials/Properties/AssemblyInfo.cs @@ -4,5 +4,5 @@ [assembly: AssemblyCompany("PepperDash Technology Corp")] [assembly: AssemblyProduct("PepperDashEssentials")] [assembly: AssemblyCopyright("Copyright © PepperDash Technology Corp 2017")] -[assembly: AssemblyVersion("1.0.5.*")] +[assembly: AssemblyVersion("1.0.6.*")] diff --git a/Essentials/PepperDashEssentials/Room/Cotija/CotijaConfig.cs b/Essentials/PepperDashEssentials/Room/Cotija/CotijaConfig.cs index ef0bae48..4bbe068e 100644 --- a/Essentials/PepperDashEssentials/Room/Cotija/CotijaConfig.cs +++ b/Essentials/PepperDashEssentials/Room/Cotija/CotijaConfig.cs @@ -5,10 +5,13 @@ using System.Text; using Crestron.SimplSharp; using PepperDash.Essentials.Core.Config; +using Newtonsoft.Json; + namespace PepperDash.Essentials { public class CotijaConfig : DeviceConfig { - public string serverUrl { get; set; } + [JsonProperty("serverUrl")] + public string ServerUrl { 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 b0d1937e..ccf34889 100644 --- a/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs +++ b/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs @@ -22,17 +22,17 @@ namespace PepperDash.Essentials CotijaConfig Config; - HttpClient Client; + //HttpClient Client; Dictionary ActionDictionary = new Dictionary(StringComparer.InvariantCultureIgnoreCase); Dictionary PushedActions = new Dictionary(); - CTimer ServerHeartbeat; + CTimer ServerHeartbeatCheckTimer; long ServerHeartbeatInterval = 20000; - CTimer ServerReconnect; + CTimer ServerReconnectTimer; long ServerReconnectInterval = 5000; @@ -48,10 +48,15 @@ namespace PepperDash.Essentials CotijaRooms = new List(); - 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); + //CrestronConsole.AddNewConsoleCommand(s => RegisterSystemToServer(), + // "CotiInitializeHttpClient", "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)); + CrestronConsole.AddNewConsoleCommand(AuthorizeSystem, + "cotijaauth", "Authorizes system to talk to cotija server", ConsoleAccessLevelEnum.AccessOperator); + + AddPostActivationAction(() => RegisterSystemToServer()); } /// @@ -67,12 +72,12 @@ namespace PepperDash.Essentials } else { - Debug.Console(1, this, "Cannot add action with key '{0}' because key already exists in ActionDictionary."); + Debug.Console(1, this, "Cannot add action with key '{0}' because key already exists in ActionDictionary.", key); } } /// - /// Removes and action from the dictionary + /// Removes an action from the dictionary /// /// public void RemoveAction(string key) @@ -81,16 +86,58 @@ namespace PepperDash.Essentials ActionDictionary.Remove(key); } - void ReconnectToServer(object o) + void ReconnectToServerTimerCallback(object o) { - RegisterSystemToServer(null); + RegisterSystemToServer(); } + /// + /// Verifies system connection with servers + /// + /// + void AuthorizeSystem(string code) + { + if (string.IsNullOrEmpty(code)) + { + CrestronConsole.ConsoleCommandResponse("Please enter a user code to authorize a system"); + return; + } + + + var req = new HttpClientRequest(); + string url = string.Format("http://{0}/api/system/grantcode/{1}", Config.ServerUrl, code); + Debug.Console(0, this, "Authorizing to: {0}", url); + + if (string.IsNullOrEmpty(Config.ServerUrl)) + { + CrestronConsole.ConsoleCommandResponse("Config URL address is not set. Check portal configuration"); + return; + } + try + { + req.Url.Parse(url); + new HttpClient().DispatchAsync(req, (r, e) => + { + if (r.Code == 200) + { + Debug.Console(0, this, "System authorized, sending config."); + RegisterSystemToServer(); + } + else + Debug.Console(0, this, "HTTP Error {0} in authorizing system", r.Code); + }); + } + catch (Exception e) + { + Debug.Console(0, this, "Error in authorizing: {0}", e); + } + } + /// /// Registers the room with the server /// /// URL of the server, including the port number, if not 80. Format: "serverUrlOrIp:port" - void RegisterSystemToServer(string command) + void RegisterSystemToServer() { try { @@ -122,23 +169,22 @@ namespace PepperDash.Essentials } else { - Client = new HttpClient(); - - HttpClientRequest request = new HttpClientRequest(); - - Client.Verbose = true; - Client.KeepAlive = true; - + var client = new HttpClient(); + client.Verbose = true; + client.KeepAlive = true; + SystemUuid = Essentials.ConfigReader.ConfigObject.SystemUuid; - string url = string.Format("http://{0}/api/system/join/{1}", Config.serverUrl, SystemUuid); + string url = string.Format("http://{0}/api/system/join/{1}", Config.ServerUrl, SystemUuid); + Debug.Console(1, this, "Sending config to {0}", url); + HttpClientRequest request = new HttpClientRequest(); request.Url.Parse(url); request.RequestType = RequestType.Post; request.Header.SetHeaderValue("Content-Type", "application/json"); request.ContentString = postBody; - Client.DispatchAsync(request, PostConnectionCallback); + client.DispatchAsync(request, PostConnectionCallback); } } @@ -158,17 +204,14 @@ namespace PepperDash.Essentials { try { - if (Client == null) - Client = new HttpClient(); - - //HttpClient client = new HttpClient(); + var client = new HttpClient(); HttpClientRequest request = new HttpClientRequest(); - Client.Verbose = true; - Client.KeepAlive = true; + client.Verbose = true; + client.KeepAlive = true; - string url = string.Format("http://{0}/api/room/{1}/status", Config.serverUrl, string.Format("{0}--{1}", SystemUuid, room.Key)); + string url = string.Format("http://{0}/api/system/{1}/status", Config.ServerUrl, SystemUuid); request.Url.Parse(url); request.RequestType = RequestType.Post; @@ -180,10 +223,17 @@ namespace PepperDash.Essentials request.ContentString = ignored; Debug.Console(1, this, "Posting to '{0}':\n{1}", url, request.ContentString); + try + { + client.DispatchAsync(request, (r, err) => { if (r != null) { Debug.Console(1, this, "Status Response Code: {0}", r.Code); } }); + } + catch (Exception e) + { - Client.DispatchAsync(request, (r, err) => { if (r != null) { Debug.Console(1, this, "Status Response Code: {0}", r.Code); } }); + Debug.Console(1, this, "PostToServer exception: {0}", e); + } - StartReconnectTimer(ServerReconnectInterval, ServerReconnectInterval); + //ResetOrStartHearbeatTimer(); } catch(Exception e) { @@ -200,11 +250,11 @@ namespace PepperDash.Essentials if(SseClient != null) SseClient.Disconnect(); - if (ServerHeartbeat != null) + if (ServerHeartbeatCheckTimer != null) { - ServerHeartbeat.Stop(); + ServerHeartbeatCheckTimer.Stop(); - ServerHeartbeat = null; + ServerHeartbeatCheckTimer = null; } } @@ -219,11 +269,11 @@ namespace PepperDash.Essentials { if (resp != null && resp.Code == 200) { - if(ServerReconnect != null) + if(ServerReconnectTimer != null) { - ServerReconnect.Stop(); + ServerReconnectTimer.Stop(); - ServerReconnect = null; + ServerReconnectTimer = null; } if (SseClient == null) @@ -249,40 +299,51 @@ namespace PepperDash.Essentials /// Executes when we don't get a heartbeat message in time. Triggers reconnect. /// /// - void HeartbeatExpired(object o) + void HeartbeatExpiredTimerCallback(object o) { - if (ServerHeartbeat != null) + if (ServerHeartbeatCheckTimer != null) { Debug.Console(1, this, "Heartbeat Timer Expired."); - ServerHeartbeat.Stop(); + ServerHeartbeatCheckTimer.Stop(); - ServerHeartbeat = null; + ServerHeartbeatCheckTimer = null; } - StartReconnectTimer(ServerReconnectInterval, ServerReconnectInterval); + StartReconnectTimer(); } - void StartReconnectTimer(long dueTime, long repeatTime) + /// + /// + /// + /// + /// + void StartReconnectTimer() { // Start the reconnect timer - ServerReconnect = new CTimer(ReconnectToServer, null, dueTime, repeatTime); - - ServerReconnect.Reset(dueTime, repeatTime); + if (ServerReconnectTimer == null) + { + ServerReconnectTimer = new CTimer(ReconnectToServerTimerCallback, null, ServerReconnectInterval, ServerReconnectInterval); + Debug.Console(1, this, "Reconnect Timer Started."); + } + ServerReconnectTimer.Reset(ServerReconnectInterval, ServerReconnectInterval); } - void StartHearbeatTimer(long dueTime, long repeatTime) + /// + /// + /// + /// + /// + void ResetOrStartHearbeatTimer() { - if (ServerHeartbeat == null) + if (ServerHeartbeatCheckTimer == null) { - ServerHeartbeat = new CTimer(HeartbeatExpired, null, dueTime, repeatTime); + ServerHeartbeatCheckTimer = new CTimer(HeartbeatExpiredTimerCallback, null, ServerHeartbeatInterval, ServerHeartbeatInterval); - Debug.Console(2, this, "Heartbeat Timer Started."); + Debug.Console(1, this, "Heartbeat Timer Started."); } - ServerHeartbeat.Reset(dueTime, repeatTime); - - Debug.Console(2, this, "Heartbeat Timer Reset."); + ServerHeartbeatCheckTimer.Reset(ServerHeartbeatInterval, ServerHeartbeatInterval); } @@ -312,7 +373,7 @@ namespace PepperDash.Essentials string uuid = Essentials.ConfigReader.ConfigObject.SystemUuid; - SseClient.Url = string.Format("http://{0}/api/system/stream/{1}", Config.serverUrl, uuid); + SseClient.Url = string.Format("http://{0}/api/system/stream/{1}", Config.ServerUrl, uuid); SseClient.Connect(); } @@ -336,101 +397,102 @@ namespace PepperDash.Essentials if (type == "hello") { - StartHearbeatTimer(ServerHeartbeatInterval, ServerHeartbeatInterval); + ResetOrStartHearbeatTimer(); } - else if (type == "/system/heartbeat") - { - StartHearbeatTimer(ServerHeartbeatInterval, ServerHeartbeatInterval); - } - else if (type == "close") - { - SseClient.Disconnect(); + else if (type == "/system/heartbeat") + { + ResetOrStartHearbeatTimer(); + } + else if (type == "close") + { + SseClient.Disconnect(); - // Start the reconnect timer - ServerReconnect = new CTimer(ConnectSseClient, null, ServerReconnectInterval, ServerReconnectInterval); + ServerHeartbeatCheckTimer.Stop(); + // Start the reconnect timer + StartReconnectTimer(); + //ServerReconnectTimer = new CTimer(ConnectSseClient, null, ServerReconnectInterval, ServerReconnectInterval); + //ServerReconnectTimer.Reset(ServerReconnectInterval, ServerReconnectInterval); + } + else + { + // Check path against Action dictionary + if (ActionDictionary.ContainsKey(type)) + { + var action = ActionDictionary[type]; - ServerReconnect.Reset(ServerReconnectInterval, ServerReconnectInterval); - } - else - { - // Check path against Action dictionary - if (ActionDictionary.ContainsKey(type)) - { - var action = ActionDictionary[type]; + if (action is Action) + { + (action as Action)(); + } + else if (action is PressAndHoldAction) + { + var stateString = messageObj["content"]["state"].Value(); - if (action is Action) - { - (action as Action)(); - } - else if (action is PressAndHoldAction) - { - var stateString = messageObj["content"]["state"].Value(); + // Look for a button press event + if (!string.IsNullOrEmpty(stateString)) + { + switch (stateString) + { + case "true": + { + if (!PushedActions.ContainsKey(type)) + { + PushedActions.Add(type, new CTimer(o => + { + (action as PressAndHoldAction)(false); + PushedActions.Remove(type); + }, null, ButtonHeartbeatInterval, ButtonHeartbeatInterval)); + } + // Maybe add an else to reset the timer + break; + } + case "held": + { + if (!PushedActions.ContainsKey(type)) + { + PushedActions[type].Reset(ButtonHeartbeatInterval, ButtonHeartbeatInterval); + } + return; + } + case "false": + { + if (PushedActions.ContainsKey(type)) + { + PushedActions[type].Stop(); + PushedActions.Remove(type); + } + break; + } + } - // Look for a button press event - if (!string.IsNullOrEmpty(stateString)) - { - switch (stateString) - { - case "true": - { - if (!PushedActions.ContainsKey(type)) - { - PushedActions.Add(type, new CTimer(o => - { - (action as PressAndHoldAction)(false); - PushedActions.Remove(type); - }, null, ButtonHeartbeatInterval, ButtonHeartbeatInterval)); - } - // Maybe add an else to reset the timer - break; - } - case "held": - { - if (!PushedActions.ContainsKey(type)) - { - PushedActions[type].Reset(ButtonHeartbeatInterval, ButtonHeartbeatInterval); - } - return; - } - case "false": - { - if (PushedActions.ContainsKey(type)) - { - PushedActions[type].Stop(); - PushedActions.Remove(type); - } - break; - } - } + (action as PressAndHoldAction)(stateString == "true"); + } + } + else if (action is Action) + { + var stateString = messageObj["content"]["state"].Value(); - (action as PressAndHoldAction)(stateString == "true"); - } - } - else if (action is Action) - { - var stateString = messageObj["content"]["state"].Value(); + if (!string.IsNullOrEmpty(stateString)) + { + (action as Action)(stateString == "true"); + } + } + else if (action is Action) + { + (action as Action)(messageObj["content"]["value"].Value()); + } + else if (action is Action) + { + (action as Action)(messageObj["content"]["value"].Value()); + } + else if (action is Action) + { + (action as Action)(messageObj["content"] + .ToObject()); + } + } - if (!string.IsNullOrEmpty(stateString)) - { - (action as Action)(stateString == "true"); - } - } - else if (action is Action) - { - (action as Action)(messageObj["content"]["value"].Value()); - } - else if (action is Action) - { - (action as Action)(messageObj["content"]["value"].Value()); - } - else if (action is Action) - { - (action as Action)(messageObj["content"] - .ToObject()); - } - } - - } + } } catch (Exception err) diff --git a/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs b/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs index 696f14f7..ad1a000b 100644 --- a/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs +++ b/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs @@ -207,11 +207,23 @@ namespace PepperDash.Essentials /// /// 1252 /// - public const uint VCRemoteViewTogglePress = 1252; + public const uint VCLayoutTogglePress = 1252; /// /// 1253 /// public const uint VCSelfViewPipTogglePress = 1253; + /// + /// 1254 + /// + public const uint VCLayoutToggleEnable = 1254; + /// + /// 1255 + /// + public const uint VCMinMaxPress = 1255; + /// + /// 1256 + /// + public const uint VCMinMaxEnable = 1256; //****************************************************** diff --git a/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddleTechPageDriver.cs b/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddleTechPageDriver.cs index 522bbca4..36363834 100644 --- a/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddleTechPageDriver.cs +++ b/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddleTechPageDriver.cs @@ -73,6 +73,7 @@ namespace PepperDash.Essentials.UIDrivers true, 3100); MenuList.SetFeedback(1, true); // initial fb + ushort count = 0; MenuList.SetItemMainText(1, "System Status"); MenuList.SetItemButtonAction(1, b => { @@ -84,19 +85,25 @@ namespace PepperDash.Essentials.UIDrivers MenuList.SetItemButtonAction(2, b => { if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechDisplayControlsVisible); MenuList.SetFeedback(2, true); - }); - - MenuList.SetItemMainText(3, "Panel Setup"); - MenuList.SetItemButtonAction(3, b => { - if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechPanelSetupVisible); - MenuList.SetFeedback(3, true); }); - MenuList.Count = 3; + count = 2; + + // Don't show panel setup on iPad or xpanel + if (TriList is Crestron.SimplSharpPro.DeviceSupport.TswFt5Button) + { + count++; + MenuList.SetItemMainText(count, "Panel Setup"); + MenuList.SetItemButtonAction(count, b => + { + if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechPanelSetupVisible); + MenuList.SetFeedback(count, true); + }); + } + + MenuList.Count = count; BuildStatusList(); - BuildDisplayList(); - SetupPinModal(); } diff --git a/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index 51d0d552..ea5e5f45 100644 --- a/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -751,7 +751,7 @@ namespace PepperDash.Essentials.UIDrivers.VC var lc = Codec as IHasCodecLayouts; if (lc != null) { - TriList.SetSigFalseAction(UIBoolJoin.VCRemoteViewTogglePress, lc.LocalLayoutToggle); + TriList.SetSigFalseAction(UIBoolJoin.VCLayoutTogglePress, lc.LocalLayoutToggle); lc.LocalLayoutFeedback.LinkInputSig(TriList.StringInput[UIStringJoin.VCLayoutModeText]); } } diff --git a/Release Package/PepperDashEssentials.cpz b/Release Package/PepperDashEssentials.cpz index 75028f14..44a47680 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 c2b8f780..acfef35c 100644 Binary files a/Release Package/PepperDashEssentials.dll and b/Release Package/PepperDashEssentials.dll differ