diff --git a/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs b/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs
index 6d5171c4..1396729a 100644
--- a/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs
+++ b/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs
@@ -21,12 +21,8 @@ namespace PepperDash.Essentials
{
public class CotijaSystemController : Device
{
- int SseMessageLengthBeforeFailureCount;
-
WebSocketClient WSClient;
- //GenericHttpSseClient SseClient;
-
///
/// Prevents post operations from stomping on each other and getting lost
///
@@ -36,8 +32,6 @@ namespace PepperDash.Essentials
public CotijaConfig Config { get; private set; }
- HttpClient Client;
-
Dictionary ActionDictionary = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
Dictionary PushedActions = new Dictionary();
@@ -55,13 +49,6 @@ namespace PepperDash.Essentials
List RoomBridges = new List();
long ButtonHeartbeatInterval = 1000;
-
- bool NeedNewClient;
-
- ///
- /// Used to count retries in PostToServer
- ///
- int RetryCounter;
///
///
@@ -278,88 +265,21 @@ namespace PepperDash.Essentials
}
///
- /// Posts a message to the server from a room
+ /// Sends a message to the server from a room
///
/// room from which the message originates
/// object to be serialized and sent in post body
- public void PostToServer(JObject o)
+ public void SendMessageToServer(JObject o)
{
- CrestronInvoke.BeginInvoke(oo =>
- {
- if (string.IsNullOrEmpty(SystemUuid))
- {
- Debug.Console(1, this, "Status post attempt before UUID is set. Ignoring.");
- return;
- }
- var ready = PostLockEvent.Wait(2000);
- if (!ready)
- {
- Debug.Console(1, this, "PostToServer failed to enter after 2 seconds. Ignoring");
- return;
- }
- PostLockEvent.Reset();
- try
- {
- if (Client == null || NeedNewClient)
- {
- NeedNewClient = false;
- Client = new HttpClient();
- }
- Client.Verbose = false;
- Client.KeepAlive = true;
+ if (WSClient != null && WSClient.Connected)
+ {
+ string message = JsonConvert.SerializeObject(o, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
- HttpClientRequest request = new HttpClientRequest();
- request.RequestType = RequestType.Post;
- string url = string.Format("http://{0}/api/system/{1}/status", Config.ServerUrl, SystemUuid);
- request.Url.Parse(url);
- request.KeepAlive = true;
- request.Header.ContentType = "application/json";
- // Ignore any null objects when serializing and remove formatting
- string ignored = JsonConvert.SerializeObject(o, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
- Debug.Console(1, this, "Posting to '{0}':\n{1}", url, ignored);
- request.ContentString = ignored;
- request.FinalizeHeader();
- Client.DispatchAsync(request, (r, err) =>
- {
- Debug.Console(1, this, "POST result: {0}", err);
+ var messageBytes = System.Text.Encoding.UTF8.GetBytes(message);
- if (err == HTTP_CALLBACK_ERROR.COMPLETED)
- {
- Debug.Console(1, this, "Status Response Code: {0}", r.Code);
- PostLockEvent.Set();
- RetryCounter = 0;
- }
- else
- {
- // Try again. This client is hosed.
- NeedNewClient = true;
- RetryCounter++;
- // instant retry on first try.
- if (RetryCounter >= 2 && RetryCounter < 5)
- CrestronEnvironment.Sleep(1000);
- else if (RetryCounter >= 5 && RetryCounter <= 10)
- CrestronEnvironment.Sleep(5000);
- // give up
- else if (RetryCounter > 10)
- {
- Debug.Console(1, this, "Giving up on server POST");
- RetryCounter = 0;
- return;
- }
- Debug.Console(1, this, "POST retry #{0}", RetryCounter);
- PostLockEvent.Set();
- PostToServer(o);
- }
- });
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error Posting to Server: {0}", e);
- PostLockEvent.Set();
- }
-
- });
+ WSClient.SendAsync(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME);
+ }
}
@@ -410,7 +330,6 @@ namespace PepperDash.Essentials
else
{
Debug.Console(1, this, "Null response received from server.");
- NeedNewClient = true;
}
}
}
@@ -485,7 +404,8 @@ namespace PepperDash.Essentials
WSClient.URL = string.Format("wss://{0}/system/join/{1}", Config.ServerUrl, this.SystemUuid);
WSClient.Connect();
Debug.Console(0, this, "Websocket connected");
- WSClient.ReceiveCallBack = WebsocketReceive;
+ WSClient.ReceiveCallBack = WebsocketReceiveCallback;
+ WSClient.SendCallBack = WebsocketSendCallback;
WSClient.ReceiveAsync();
@@ -516,7 +436,6 @@ namespace PepperDash.Essentials
// ***********************************
}
-
///
/// Resets reconnect timer and updates usercode
///
@@ -541,7 +460,7 @@ namespace PepperDash.Essentials
///
///
///
- int WebsocketReceive(byte[] data, uint length, WebSocketClient.WEBSOCKET_PACKET_TYPES opcode,
+ int WebsocketReceiveCallback(byte[] data, uint length, WebSocketClient.WEBSOCKET_PACKET_TYPES opcode,
WebSocketClient.WEBSOCKET_RESULT_CODES err)
{
var rx = System.Text.Encoding.UTF8.GetString(data, 0, (int)length);
@@ -551,6 +470,18 @@ namespace PepperDash.Essentials
return 1;
}
+ ///
+ /// Callback to catch possible errors in sending via the websocket
+ ///
+ ///
+ ///
+ int WebsocketSendCallback(Crestron.SimplSharp.CrestronWebSocketClient.WebSocketClient.WEBSOCKET_RESULT_CODES result)
+ {
+ Debug.Console(2, "SendCallback result: {0}", result);
+
+ return 1;
+ }
+
///
///
///
@@ -558,119 +489,122 @@ namespace PepperDash.Essentials
///
void ParseStreamRx(string message)
{
- Debug.Console(1, this, "Message RX: '{0}'", message);
- try
+ if(string.IsNullOrEmpty(message))
+ return;
+
+ Debug.Console(1, this, "Message RX: '{0}'", message);
+ try
+ {
+ var messageObj = JObject.Parse(message);
+
+ var type = messageObj["type"].Value();
+
+ if (type == "hello")
{
- var messageObj = JObject.Parse(message);
+ ResetOrStartHearbeatTimer();
+ }
+ else if (type == "/system/heartbeat")
+ {
+ HandleHeartBeat(messageObj["content"]);
+ }
+ else if (type == "close")
+ {
+ WSClient.Disconnect();
- var type = messageObj["type"].Value();
-
- if (type == "hello")
- {
- ResetOrStartHearbeatTimer();
- }
- else if (type == "/system/heartbeat")
+ ServerHeartbeatCheckTimer.Stop();
+ // Start the reconnect timer
+ StartReconnectTimer();
+ }
+ else
+ {
+ // Check path against Action dictionary
+ if (ActionDictionary.ContainsKey(type))
{
- HandleHeartBeat(messageObj["content"]);
- }
- else if (type == "close")
- {
- WSClient.Disconnect();
+ var action = ActionDictionary[type];
- ServerHeartbeatCheckTimer.Stop();
- // Start the reconnect timer
- StartReconnectTimer();
+ 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;
+ }
+ }
+
+ (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());
+ }
}
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();
-
- // 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();
-
- 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());
- }
- }
- else
- {
- Debug.Console(1, this, "-- Warning: Incoming message has no registered handler");
- }
+ Debug.Console(1, this, "-- Warning: Incoming message has no registered handler");
}
- }
- catch (Exception err)
- {
- Debug.Console(1, "SseMessageLengthBeforeFailureCount: {0}", SseMessageLengthBeforeFailureCount);
- SseMessageLengthBeforeFailureCount = 0;
- Debug.Console(1, this, "Unable to parse message: {0}", err);
- }
+ }
+ }
+ catch (Exception err)
+ {
+ //Debug.Console(1, "SseMessageLengthBeforeFailureCount: {0}", SseMessageLengthBeforeFailureCount);
+ //SseMessageLengthBeforeFailureCount = 0;
+ Debug.Console(1, this, "Unable to parse message: {0}", err);
+ }
}
}
}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Room/Cotija/RoomBridges/CotijaDdvc01RoomBridge.cs b/Essentials/PepperDashEssentials/Room/Cotija/RoomBridges/CotijaDdvc01RoomBridge.cs
index 324643fa..88720f3e 100644
--- a/Essentials/PepperDashEssentials/Room/Cotija/RoomBridges/CotijaDdvc01RoomBridge.cs
+++ b/Essentials/PepperDashEssentials/Room/Cotija/RoomBridges/CotijaDdvc01RoomBridge.cs
@@ -456,7 +456,7 @@ namespace PepperDash.Essentials.Room.Cotija
/// The contents of the content object
void PostStatusMessage(object contentObject)
{
- Parent.PostToServer(JObject.FromObject(new
+ Parent.SendMessageToServer(JObject.FromObject(new
{
type = "/room/status/",
content = contentObject
@@ -470,7 +470,7 @@ namespace PepperDash.Essentials.Room.Cotija
///
void PostMessage(string messageType, object contentObject)
{
- Parent.PostToServer(JObject.FromObject(new
+ Parent.SendMessageToServer(JObject.FromObject(new
{
type = messageType,
content = contentObject
diff --git a/Essentials/PepperDashEssentials/Room/Cotija/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs b/Essentials/PepperDashEssentials/Room/Cotija/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs
index ccd44070..85518346 100644
--- a/Essentials/PepperDashEssentials/Room/Cotija/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs
+++ b/Essentials/PepperDashEssentials/Room/Cotija/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs
@@ -102,7 +102,7 @@ namespace PepperDash.Essentials
JObject message = new JObject();
message.Add("type", "/room/shutdown/");
message.Add("content", roomStatus);
- Parent.PostToServer(message);
+ Parent.SendMessageToServer(message);
}
///
@@ -117,7 +117,7 @@ namespace PepperDash.Essentials
JObject message = new JObject();
message.Add("type", "/room/shutdown/");
message.Add("content", roomStatus);
- Parent.PostToServer(message);
+ Parent.SendMessageToServer(message);
}
///
@@ -133,7 +133,7 @@ namespace PepperDash.Essentials
JObject message = new JObject();
message.Add("type", "/room/shutdown/");
message.Add("content", roomStatus);
- Parent.PostToServer(message);
+ Parent.SendMessageToServer(message);
// equivalent JS message:
// Post( { type: '/room/status/', content: { shutdown: 'hasStarted', duration: Room.ShutdownPromptTimer.SecondsToCount })
}
@@ -150,7 +150,7 @@ namespace PepperDash.Essentials
JObject message = new JObject();
message.Add("type", "/room/status/");
message.Add("content", roomStatus);
- Parent.PostToServer(message);
+ Parent.SendMessageToServer(message);
}
///
@@ -165,7 +165,7 @@ namespace PepperDash.Essentials
JObject message = new JObject();
message.Add("type", "/room/status/");
message.Add("content", roomStatus);
- Parent.PostToServer(message);
+ Parent.SendMessageToServer(message);
}
///
@@ -193,7 +193,7 @@ namespace PepperDash.Essentials
message.Add("type", "/room/status/");
message.Add("content", roomStatus);
- Parent.PostToServer(message);
+ Parent.SendMessageToServer(message);
}
void Room_CurrentVolumeDeviceChange(object sender, VolumeDeviceChangeEventArgs e)
@@ -245,7 +245,7 @@ namespace PepperDash.Essentials
message.Add("type", "/room/status/");
message.Add("content", roomStatus);
- Parent.PostToServer(message);
+ Parent.SendMessageToServer(message);
}
}
@@ -297,7 +297,7 @@ namespace PepperDash.Essentials
message.Add("type", "/room/status/");
message.Add("content", roomStatus);
- Parent.PostToServer(message);
+ Parent.SendMessageToServer(message);
}
else
{
@@ -362,7 +362,7 @@ namespace PepperDash.Essentials
message.Add("type", "/room/status/");
message.Add("content", roomStatus);
- Parent.PostToServer(message);
+ Parent.SendMessageToServer(message);
}
diff --git a/Release Package/PepperDashEssentials.cpz b/Release Package/PepperDashEssentials.cpz
index 124d90b9..97c66930 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 4d3bb3d0..696e986d 100644
Binary files a/Release Package/PepperDashEssentials.dll and b/Release Package/PepperDashEssentials.dll differ