From 99da6debdca61f3bf49529df7bafea5f549553ac Mon Sep 17 00:00:00 2001 From: Heath Volmer Date: Wed, 19 Sep 2018 11:46:52 -0600 Subject: [PATCH] Switched Websocket to synchronous Send method. Seems to prevent data loss --- .../AppServer/CotijaSystemController.cs | 109 ++------------- .../Messengers/AtcDdvc01Messenger.cs | 127 ++++++++++++++++++ .../RoomBridges/CotijaDdvc01RoomBridge.cs | 12 +- .../CotijaEssentialsHuddleSpaceRoomBridge.cs | 5 +- .../PepperDashEssentials.csproj | 1 + .../EssentialsHuddlePanelAvFunctionsDriver.cs | 2 +- devjson commands.json | 3 + essentials-framework | 2 +- 8 files changed, 156 insertions(+), 105 deletions(-) create mode 100644 PepperDashEssentials/AppServer/Messengers/AtcDdvc01Messenger.cs diff --git a/PepperDashEssentials/AppServer/CotijaSystemController.cs b/PepperDashEssentials/AppServer/CotijaSystemController.cs index f72857d1..a6b06e55 100644 --- a/PepperDashEssentials/AppServer/CotijaSystemController.cs +++ b/PepperDashEssentials/AppServer/CotijaSystemController.cs @@ -239,6 +239,7 @@ namespace PepperDash.Essentials if (r.Code == 200) { Debug.Console(0, "System authorized, sending config."); +#warning This registration may need to wait for config ready. Maybe. RegisterSystemToServer(); } else if (r.Code == 404) @@ -301,102 +302,8 @@ namespace PepperDash.Essentials { ConnectWebsocketClient(); return; - - //var ready = RegisterLockEvent.Wait(20000); - //if (!ready) - //{ - // Debug.Console(1, this, "RegisterSystemToServer event failed to clear after 20 seconds. Ignoring"); - // //return; - //} - //RegisterLockEvent.Reset(); - - //try - //{ - // var confObject = ConfigReader.ConfigObject; - // confObject.Info.RuntimeInfo.AppName = Assembly.GetExecutingAssembly().GetName().Name; - // var version = Assembly.GetExecutingAssembly().GetName().Version; - // confObject.Info.RuntimeInfo.AssemblyVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build); - - // string postBody = JsonConvert.SerializeObject(confObject); - // SystemUuid = confObject.SystemUuid; - - // if (string.IsNullOrEmpty(postBody)) - // { - // Debug.Console(1, this, "ERROR: Config body is empty. Cannot register with server."); - // } - // else - // { - // var regClient = new HttpClient(); - // regClient.Verbose = true; - // regClient.KeepAlive = true; - - // string url = string.Format("http://{0}/api/system/join/{1}", Config.ServerUrl, SystemUuid); - // Debug.Console(1, this, "Joining server at {0}", url); - - // HttpClientRequest request = new HttpClientRequest(); - // request.Url.Parse(url); - // request.RequestType = RequestType.Post; - // request.Header.SetHeaderValue("Content-Type", "application/json"); - // request.ContentString = postBody; - - // regClient.DispatchAsync(request, RegistrationConnectionCallback); - // } - - //} - //catch (Exception e) - //{ - // Debug.Console(0, this, "ERROR: Initilizing app server controller: {0}", e); - // RegisterLockEvent.Set(); - // StartReconnectTimer(); - //} - } - ///// - ///// The callback that fires when we get a response from our registration attempt - ///// - ///// - ///// - //void RegistrationConnectionCallback(HttpClientResponse resp, HTTP_CALLBACK_ERROR err) - //{ - // CheckHttpDebug(resp, err); - // try - // { - // if (resp != null && resp.Code == 200) - // { - // StopReconnectTimer(); - - // // Success here! - // ConnectStreamClient(); - // } - // else - // { - // if (resp != null) - // { - // if (resp.Code == 502) - // { - // Debug.Console(1, this, "Cannot reach App Server behind web server. Check that service/app is running on server"); - // } - // else - // { - // Debug.Console(1, this, "Error response from server: {0}\n{1}", resp.Code, err); - // } - // } - // else - // { - // Debug.Console(1, this, "No response. Server is likely unreachable"); - // } - // StartReconnectTimer(); - // } - // } - // catch (Exception e) - // { - // Debug.Console(1, this, "Error Initializing Stream Client: {0}", e); - // StartReconnectTimer(); - // RegisterLockEvent.Set(); - // } - //} - /// /// Connects the Websocket Client /// @@ -500,8 +407,16 @@ namespace PepperDash.Essentials string message = JsonConvert.SerializeObject(o, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); Debug.Console(1, this, "Message TX: {0}", message); var messageBytes = System.Text.Encoding.UTF8.GetBytes(message); - WSClient.SendAsync(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME); + var result = WSClient.Send(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME); + if (result != WebSocketClient.WEBSOCKET_RESULT_CODES.WEBSOCKET_CLIENT_SUCCESS) + { + Debug.Console(1, this, "Socket send result error: {0}", result); + } } + else if (!WSClient.Connected) + { + Debug.Console(1, this, "Cannot send. Not connected {0}"); + } } /// @@ -703,7 +618,7 @@ namespace PepperDash.Essentials { if(result != WebSocketClient.WEBSOCKET_RESULT_CODES.WEBSOCKET_CLIENT_SUCCESS) Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "SendCallback questionable result: {0}", result); - return 0; + return 1; } /// @@ -716,7 +631,7 @@ namespace PepperDash.Essentials if(string.IsNullOrEmpty(message)) return; - Debug.Console(1, this, "Message RX: '{0}'", message); + Debug.Console(1, this, "Message RX: {0}", message); try { var messageObj = JObject.Parse(message); diff --git a/PepperDashEssentials/AppServer/Messengers/AtcDdvc01Messenger.cs b/PepperDashEssentials/AppServer/Messengers/AtcDdvc01Messenger.cs new file mode 100644 index 00000000..c36702aa --- /dev/null +++ b/PepperDashEssentials/AppServer/Messengers/AtcDdvc01Messenger.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.EthernetCommunication; + +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.AppServer.Messengers +{ + public class Ddvc01AtcMessenger : MessengerBase + { + BasicTriList EISC; + + const uint BKeypad1 = 201; + const uint BKeypad2 = 202; + const uint BKeypad3 = 203; + const uint BKeypad4 = 204; + const uint BKeypad5 = 205; + const uint BKeypad6 = 206; + const uint BKeypad7 = 207; + const uint BKeypad8 = 208; + const uint BKeypad9 = 209; + const uint BKeypad0 = 210; + const uint BKeypadStar = 211; + const uint BKeypadPound = 212; + const uint BDialHangup = 221; + const uint BIncomingAnswer = 251; + const uint BIncomingReject = 252; + const uint BSpeedDial1 = 241; + const uint BSpeedDial2 = 242; + const uint BSpeedDial3 = 243; + const uint BSpeedDial4 = 244; + + const uint BIsOnHook = 222; + const uint BIsOffHook = 224; + const uint BDialHangupIsVisible = 251; + const uint BCallIsIncoming = 254; + const uint BSpeedDialIsVisible1 = 261; + const uint BSpeedDialIsVisible2 = 262; + const uint BSpeedDialIsVisible3 = 263; + const uint BSpeedDialIsVisible4 = 264; + + + const uint SCurrentDialString = 201; + const uint SSpeedDialName1 = 241; + const uint SSpeedDialName2 = 242; + const uint SSpeedDialName3 = 243; + const uint SSpeedDialName4 = 244; + + /// + /// + /// + /// + /// + public Ddvc01AtcMessenger(BasicTriList eisc, string messagePath) + : base(messagePath) + { + EISC = eisc; + + } + + /// + /// + /// + void SendFullStatus() + { + this.PostStatusMessage(new + { + atc = new + { + callIsIncoming = EISC.GetBool(BCallIsIncoming), + isOnHook = EISC.GetBool(BIsOnHook), + isOffHook = EISC.GetBool(BIsOffHook), + dialHangupIsVisible = EISC.GetBool(BDialHangupIsVisible), + currentDialString = EISC.GetString(SCurrentDialString), + } + }); + } + + /// + /// + /// + /// + protected override void CustomRegisterWithAppServer(CotijaSystemController appServerController) + { + Action send = this.PostStatusMessage; + EISC.SetBoolSigAction(BIsOffHook, b => send(new { isOffHook = b })); + EISC.SetBoolSigAction(BIsOnHook, b => send(new { isOnHook = b })); + EISC.SetBoolSigAction(BDialHangupIsVisible, b => send(new { dialHangupIsVisible = b })); + EISC.SetBoolSigAction(BCallIsIncoming, b => send(new { callIsIncoming = b })); + EISC.SetStringSigAction(SCurrentDialString, s => send(new { currentDialString = s })); + + // Add press and holds using helper + Action addPHAction = (s, u) => + AppServerController.AddAction(MessagePath + s, new PressAndHoldAction(b => EISC.SetBool(u, b))); + addPHAction("/dial1", BKeypad1); + addPHAction("/dial2", BKeypad2); + addPHAction("/dial3", BKeypad3); + addPHAction("/dial4", BKeypad4); + addPHAction("/dial5", BKeypad5); + addPHAction("/dial6", BKeypad6); + addPHAction("/dial7", BKeypad7); + addPHAction("/dial8", BKeypad8); + addPHAction("/dial9", BKeypad9); + addPHAction("/dial0", BKeypad0); + addPHAction("/dialStar", BKeypadStar); + addPHAction("/dialPound", BKeypadPound); + + // Add straight calls + Action addAction = (s, u) => + AppServerController.AddAction(MessagePath + s, new Action(() => EISC.PulseBool(u, 100))); + addAction("/dialHangup", BDialHangup); + addAction("/incomingAnswer", BIncomingAnswer); + addAction("/incomingReject", BIncomingReject); + addAction("/speedDial1", BSpeedDial1); + addAction("/speedDial2", BSpeedDial2); + addAction("/speedDial3", BSpeedDial3); + addAction("/speedDial4", BSpeedDial4); + + AppServerController.AddAction(MessagePath + "/fullStatus", new Action(SendFullStatus)); + } + } +} \ No newline at end of file diff --git a/PepperDashEssentials/AppServer/RoomBridges/CotijaDdvc01RoomBridge.cs b/PepperDashEssentials/AppServer/RoomBridges/CotijaDdvc01RoomBridge.cs index 25c122df..ddff3e14 100644 --- a/PepperDashEssentials/AppServer/RoomBridges/CotijaDdvc01RoomBridge.cs +++ b/PepperDashEssentials/AppServer/RoomBridges/CotijaDdvc01RoomBridge.cs @@ -10,6 +10,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PepperDash.Core; +using PepperDash.Essentials.AppServer.Messengers; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Room.Config; @@ -145,6 +146,8 @@ namespace PepperDash.Essentials.Room.Cotija CotijaDdvc01DeviceBridge SourceBridge; + Ddvc01AtcMessenger AtcMessenger; + /// /// @@ -182,6 +185,9 @@ namespace PepperDash.Essentials.Room.Cotija SetupFunctions(); SetupFeedbacks(); + AtcMessenger = new Ddvc01AtcMessenger(EISC, "/atc"); + AtcMessenger.RegisterWithAppServer(Parent); + EISC.SigChange += EISC_SigChange; EISC.OnlineStatusChange += (o, a) => { @@ -216,8 +222,6 @@ namespace PepperDash.Essentials.Room.Cotija } }, "mobilebridgedump", "Dumps DDVC01 bridge EISC data b,u,s", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => LoadConfigValues(), "loadddvc", "", ConsoleAccessLevelEnum.AccessOperator); - return base.CustomActivate(); } @@ -227,7 +231,6 @@ namespace PepperDash.Essentials.Room.Cotija /// void SetupFunctions() { - Parent.AddAction(@"/room/room1/status", new Action(SendFullStatus)); Parent.AddAction(@"/room/room1/source", new Action(c => @@ -465,6 +468,9 @@ namespace PepperDash.Essentials.Room.Cotija ConfigIsLoaded = true; } + /// + /// + /// void SendFullStatus() { if (ConfigIsLoaded) diff --git a/PepperDashEssentials/AppServer/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs b/PepperDashEssentials/AppServer/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs index 815aa3e8..35acefc6 100644 --- a/PepperDashEssentials/AppServer/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs +++ b/PepperDashEssentials/AppServer/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs @@ -82,7 +82,7 @@ namespace PepperDash.Essentials var currentVolumeDevice = volumeRoom.CurrentVolumeControls as IBasicVolumeWithFeedback; if (currentVolumeDevice != null) { - currentVolumeDevice.MuteFeedback.OutputChange += VolumeLevelFeedback_OutputChange; + currentVolumeDevice.MuteFeedback.OutputChange += MuteFeedback_OutputChange; currentVolumeDevice.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange; } } @@ -470,8 +470,7 @@ namespace PepperDash.Essentials }; } return vtc; - } - + } } /// diff --git a/PepperDashEssentials/PepperDashEssentials.csproj b/PepperDashEssentials/PepperDashEssentials.csproj index 1bcd3259..1bb81720 100644 --- a/PepperDashEssentials/PepperDashEssentials.csproj +++ b/PepperDashEssentials/PepperDashEssentials.csproj @@ -104,6 +104,7 @@ + diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs index abdfeea6..e18801ea 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs @@ -741,7 +741,7 @@ namespace PepperDash.Essentials _CurrentRoom.ShutdownPromptTimer.HasFinished -= ShutdownPromptTimer_HasFinished; _CurrentRoom.ShutdownPromptTimer.WasCancelled -= ShutdownPromptTimer_WasCancelled; - _CurrentRoom.OnFeedback.OutputChange += CurrentRoom_OnFeedback_OutputChange; + _CurrentRoom.OnFeedback.OutputChange -= CurrentRoom_OnFeedback_OutputChange; _CurrentRoom.IsWarmingUpFeedback.OutputChange -= CurrentRoom_IsWarmingFeedback_OutputChange; _CurrentRoom.IsCoolingDownFeedback.OutputChange -= IsCoolingDownFeedback_OutputChange; } diff --git a/devjson commands.json b/devjson commands.json index 67ee4df4..55bc8bda 100644 --- a/devjson commands.json +++ b/devjson commands.json @@ -29,3 +29,6 @@ devjson:1 {"deviceKey":"microphonePrivacyController-1", "methodName":"TogglePriv devjson:1 {"deviceKey":"room1.InCallFeedback","methodName":"SetTestValue", "params": [ true ]} devjson:1 {"deviceKey":"room1.InCallFeedback","methodName":"ClearTestValue", "params": []} + +devjson:10 {"deviceKey":"mobileControlBridge-essentialsHuddle","methodName":"TestOne"} +devjson:10 {"deviceKey":"mobileControlBridge-essentialsHuddle","methodName":"TestMulti"} diff --git a/essentials-framework b/essentials-framework index fb02dac4..7d08a09d 160000 --- a/essentials-framework +++ b/essentials-framework @@ -1 +1 @@ -Subproject commit fb02dac4bbf50cc5e17a41539be6b5b5ea8752f1 +Subproject commit 7d08a09d5f7a03164907a5bbf15e80f49bf7658c