private void ClientOnReceivedData(TtpSshClient client, TesiraMessage message) { try { JToken json; switch (message.Type) { case TesiraMessageType.OkWithResponse: var response = message as TesiraResponse; if (response == null) { return; } if (response.Command == "DEVICE get networkStatus") { json = response.TryParseResponse(); if (json != null) { Debug.WriteSuccess("Network Config", "\r\n" + json.ToString(Formatting.Indented)); } } break; case TesiraMessageType.Notification: json = message.TryParseResponse(); if (json != null) { Debug.WriteSuccess(json.ToString(Formatting.Indented)); } break; default: break; } } catch (Exception e) { CloudLog.Exception(e, "Error handling received data"); } if (ReceivedData == null) { return; } try { ReceivedData(client, message); } catch (Exception e) { CloudLog.Exception(e, "Error calling event handler"); } }
private void OnReceivedData(TtpSshClient client, TesiraMessage message) { if (message.Type != TesiraMessageType.Notification && message.Id == InstanceTag) { var response = message as TesiraResponse; if (response != null && response.Type == TesiraMessageType.OkWithResponse) { Debug.WriteSuccess(GetType().Name + " \"" + InstanceTag + "\"", "Received {0}\r\n{1}", response.AttributeCode, response.TryParseResponse().ToString(Formatting.Indented)); ReceivedResponse(response); } } else if (message.Type == TesiraMessageType.Notification && Subscriptions.ContainsKey(message.Id)) { var response = message as TesiraNotification; if (response != null) { Debug.WriteSuccess(GetType().Name + " \"" + InstanceTag + "\"", "Received notification \"{0}\"\r\n{1}", Subscriptions[message.Id], response.TryParseResponse().ToString(Formatting.Indented)); ReceivedNotification(Subscriptions[message.Id], response.TryParseResponse()); } } }
private object SshCommsProcess(object userSpecific) { try { Thread.Sleep(1000); Debug.WriteInfo(string.Format("{0} attempting connection to {1}", GetType().Name, _address)); var firstFail = false; while (!_client.IsConnected && _reconnect) { try { ConnectionStatus = ClientStatus.AttemptingConnection; _client.Connect(); } catch { ConnectionStatus = ClientStatus.Disconnected; if (!firstFail) { CloudLog.Warn("{0} could not connect to {1}, will retry every 30 seconds until connected", GetType().Name, _address); firstFail = true; } Thread.Sleep(30000); } } if (!_client.IsConnected && !_reconnect) { _client.Dispose(); _client = null; ConnectionStatus = ClientStatus.Disconnected; return(null); } CloudLog.Notice("{0} Connected to {1}", GetType().Name, _address); _shell = _client.CreateShellStream("terminal", 80, 24, 800, 600, BufferSize); var buffer = new byte[BufferSize]; var dataCount = 0; try { while (_programRunning && _client.IsConnected) { while (_shell.CanRead && _shell.DataAvailable) { var incomingData = new byte[BufferSize]; var incomingDataCount = _shell.Read(incomingData, 0, incomingData.Length); #if DEBUG _stopWatch.Start(); Debug.WriteSuccess("Tesira rx {0} bytes", incomingDataCount); //Debug.WriteNormal(Debug.AnsiBlue + // Tools.GetBytesAsReadableString(incomingData, 0, incomingDataCount, true) + // Debug.AnsiReset); #endif if (!Connected && Encoding.ASCII.GetString(incomingData, 0, incomingDataCount) .Contains("Welcome to the Tesira Text Protocol Server...")) { _requestsSent.Clear(); _requestsAwaiting.Clear(); _sendQueue.Enqueue("SESSION set verbose true"); ConnectionStatus = ClientStatus.Connected; _keepAliveTimer = new CTimer(specific => { #if DEBUG Debug.WriteInfo(GetType().Name + " Sending KeepAlive"); #endif _client.SendKeepAlive(); }, null, KeepAliveTime, KeepAliveTime); } else if (Connected) { for (var i = 0; i < incomingDataCount; i++) { buffer[dataCount] = incomingData[i]; if (buffer[dataCount] == 10) { //skip } else if (buffer[dataCount] != 13) { dataCount++; } else { if (dataCount == 0) { continue; } var line = Encoding.UTF8.GetString(buffer, 0, dataCount); dataCount = 0; #if DEBUG Debug.WriteSuccess("Tesira Rx Line", Debug.AnsiPurple + line + Debug.AnsiReset); #endif TesiraMessage message = null; if (line == "+OK") { var request = _requestsAwaiting.TryToDequeue(); if (request != null) { #if DEBUG Debug.WriteInfo("Request Response Received", request); Debug.WriteSuccess(line); #endif message = new TesiraResponse(request, null); } } else if (line.StartsWith("+OK ")) { var request = _requestsAwaiting.TryToDequeue(); if (request != null) { #if DEBUG Debug.WriteInfo("Request Response Received", request); Debug.WriteSuccess(line); #endif message = new TesiraResponse(request, line.Substring(4)); } } else if (line.StartsWith("-ERR ")) { var request = _requestsAwaiting.TryToDequeue(); if (request != null) { #if DEBUG Debug.WriteInfo("Request Response Received", request); Debug.WriteError(line); #endif message = new TesiraErrorResponse(request, line.Substring(5)); } else { Debug.WriteError("Error received and request queue returned null!"); Debug.WriteError(line); Debug.WriteError("Clearing all queues!"); _requestsSent.Clear(); _requestsAwaiting.Clear(); } } else if (line.StartsWith("! ")) { #if DEBUG Debug.WriteWarn("Notification Received"); Debug.WriteWarn(line); #endif message = new TesiraNotification(line.Substring(2)); } else if (!_requestsSent.IsEmpty) { Debug.WriteWarn("Last sent request", _requestsSent.Peek()); if (_requestsSent.Peek() == line) { _requestsAwaiting.Enqueue(_requestsSent.Dequeue()); #if DEBUG Debug.WriteNormal("Now awaiting for response for command", line); #endif } } if (message != null && ReceivedData != null && message.Type != TesiraMessageType.ErrorResponse) { if (ReceivedData == null) { continue; } try { _timeOutCount = 0; ReceivedData(this, message); } catch (Exception e) { CloudLog.Exception(e, "Error calling event handler"); } } else if (message != null && message.Type == TesiraMessageType.ErrorResponse) { _timeOutCount = 0; CloudLog.Error("Error message from Tesira: \"{0}\"", message.Message); } } } } #if DEBUG _stopWatch.Stop(); Debug.WriteNormal("Time to process: {0} ms", _stopWatch.ElapsedMilliseconds); _stopWatch.Reset(); #endif CrestronEnvironment.AllowOtherAppsToRun(); } if (!_programRunning || !_client.IsConnected) { break; } #if DEBUG //Debug.WriteNormal(Debug.AnsiBlue + // string.Format( // "Shell Can Write = {0}, _sendQueue = {1}, _requestsSent = {2}, _requestsAwaiting = {3}", // _shell.CanWrite, _sendQueue.Count, _requestsSent.Count, // _requestsAwaiting.Count) + Debug.AnsiReset); #endif if (_shell.CanWrite && !_sendQueue.IsEmpty && _requestsSent.IsEmpty && _requestsAwaiting.IsEmpty) { var s = _sendQueue.Dequeue(); if (_keepAliveTimer != null && !_keepAliveTimer.Disposed) { _keepAliveTimer.Reset(KeepAliveTime, KeepAliveTime); } #if DEBUG Debug.WriteWarn("Tesira Tx", s); #endif _timeOutCount = 0; _shell.WriteLine(s); _requestsSent.Enqueue(s); Thread.Sleep(20); } else if (!_requestsSent.IsEmpty || !_requestsAwaiting.IsEmpty) { _timeOutCount++; if (_timeOutCount > 100) { CloudLog.Warn( "Error waiting to send requests in {0}, _requestsAwaiting.Count = {1}" + "and _requestsSent.Count = {2}. Clearing queues!", GetType().Name, _requestsAwaiting.Count, _requestsSent.Count); _requestsAwaiting.Clear(); _requestsSent.Clear(); _timeOutCount = 0; } Thread.Sleep(20); } } } catch (Exception e) { CloudLog.Exception(e); } _loggedIn = false; if (_keepAliveTimer != null && !_keepAliveTimer.Disposed) { _keepAliveTimer.Stop(); _keepAliveTimer.Dispose(); _keepAliveTimer = null; } if (_client != null && _client.IsConnected) { _client.Dispose(); _client = null; } CloudLog.Notice("{0} Disconnected from {1}", GetType().Name, _address); } catch (Exception e) { CloudLog.Exception(e, "Error in {0}.SshCommsProcess()", GetType().Name); } ConnectionStatus = ClientStatus.Disconnected; if (!_reconnect || !_programRunning) { return(null); } Thread.Sleep(1000); CloudLog.Notice("Attempting reconnect to Tesira at {0}", _address); ConnectionStatus = ClientStatus.AttemptingConnection; Connect(); return(null); }