diff --git a/Pepperdash Core/CLZ Builds/PepperDash_Core.clz b/Pepperdash Core/CLZ Builds/PepperDash_Core.clz index 1257056..e3db02e 100644 Binary files a/Pepperdash Core/CLZ Builds/PepperDash_Core.clz and b/Pepperdash Core/CLZ Builds/PepperDash_Core.clz differ diff --git a/Pepperdash Core/CLZ Builds/PepperDash_Core.dll b/Pepperdash Core/CLZ Builds/PepperDash_Core.dll index 04c7033..361097b 100644 Binary files a/Pepperdash Core/CLZ Builds/PepperDash_Core.dll and b/Pepperdash Core/CLZ Builds/PepperDash_Core.dll differ diff --git a/Pepperdash Core/Pepperdash Core.suo b/Pepperdash Core/Pepperdash Core.suo index 474dceb..a7a375e 100644 Binary files a/Pepperdash Core/Pepperdash Core.suo and b/Pepperdash Core/Pepperdash Core.suo differ diff --git a/Pepperdash Core/Pepperdash Core/Comm/CommunicationGather.cs b/Pepperdash Core/Pepperdash Core/Comm/CommunicationGather.cs index 4e5bf12..3d03f2e 100644 --- a/Pepperdash Core/Pepperdash Core/Comm/CommunicationGather.cs +++ b/Pepperdash Core/Pepperdash Core/Comm/CommunicationGather.cs @@ -30,7 +30,7 @@ namespace PepperDash.Core /// /// The communication port that this gathers on /// - public IBasicCommunication Port { get; private set; } + public ICommunicationReceiver Port { get; private set; } /// /// Default false. If true, the delimiter will be included in the line output @@ -55,7 +55,7 @@ namespace PepperDash.Core /// /// /// - public CommunicationGather(IBasicCommunication port, char delimiter) + public CommunicationGather(ICommunicationReceiver port, char delimiter) { Port = port; Delimiter = delimiter; @@ -67,7 +67,7 @@ namespace PepperDash.Core /// /// /// - public CommunicationGather(IBasicCommunication port, string delimiter) + public CommunicationGather(ICommunicationReceiver port, string delimiter) { Port = port; StringDelimiter = delimiter; diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericHttpSseClient.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericHttpSseClient.cs new file mode 100644 index 0000000..9e5121f --- /dev/null +++ b/Pepperdash Core/Pepperdash Core/Comm/GenericHttpSseClient.cs @@ -0,0 +1,254 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronIO; +using Crestron.SimplSharp.Net.Http; + +namespace PepperDash.Core +{ + public class GenericHttpSseClient : ICommunicationReceiver + { + public event EventHandler BytesReceived; + public event EventHandler TextReceived; + + public bool IsConnected + { + get; + private set; + } + + public string Key + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public string Url { get; set; } + + HttpClient Client; + HttpClientRequest Request; + + public GenericHttpSseClient(string key, string name) + { + Key = key; + Name = name; + } + + public void Connect() + { + InitiateConnection(Url); + } + + public void Disconnect() + { + CloseConnection(null); + } + + public void InitiateConnection(string url) + { + CrestronInvoke.BeginInvoke(o => + { + try + { + if(string.IsNullOrEmpty(url)) + { + Debug.Console(0, this, "Error connecting to Server. No URL specified"); + return; + } + + Client = new HttpClient(); + Request = new HttpClientRequest(); + Client.Verbose = true; + Client.KeepAlive = true; + Request.Url.Parse(url); + Request.RequestType = RequestType.Get; + Request.Header.SetHeaderValue("Accept", "text/event-stream"); + + // In order to get a handle on the response stream, we have to get + // the request stream first. Boo + Client.BeginGetRequestStream(GetRequestStreamCallback, Request, null); + CrestronConsole.PrintLine("Request made!"); + } + catch (Exception e) + { + ErrorLog.Notice("Exception occured in AsyncWebPostHttps(): " + e.ToString()); + } + }); + } + + public void CloseConnection(string s) + { + if (Client != null) + { + Client.Abort(); + IsConnected = false; + + Debug.Console(1, this, "Client Disconnected"); + } + } + + private void GetRequestStreamCallback(HttpClientRequest request, HTTP_CALLBACK_ERROR error, object status) + { +#warning Explore simplifying this later.... + + try + { + // End the the async request operation and return the data stream + Stream requestStream = request.ThisClient.EndGetRequestStream(request, null); + // If this were something other than a GET we could write to the stream here + + // Closing makes the request happen + requestStream.Close(); + + // Get a handle on the response stream. + request.ThisClient.BeginGetResponseStream(GetResponseStreamCallback, request, status); + } + catch (Exception e) + { + ErrorLog.Notice("Exception occured in GetSecureRequestStreamCallback(): " + e.ToString()); + } + } + + /// + /// + /// + /// + /// + /// + private void GetResponseStreamCallback(HttpClientRequest request, HTTP_CALLBACK_ERROR error, object status) + { + try + { + // This closes up the GetResponseStream async + var response = request.ThisClient.EndGetResponseStream(request); + + response.DataConnection.OnBytesReceived += new EventHandler(DataConnection_OnBytesReceived); + + IsConnected = true; + + Debug.Console(1, this, "Client Disconnected"); + +#warning Need to explore using a heartbeat to verify connection to the server + + Stream streamResponse = response.ContentStream; + // Object containing various states to be passed back to async callback below + RequestState asyncState = new RequestState(); + asyncState.Request = request; + asyncState.Response = response; + asyncState.StreamResponse = streamResponse; + asyncState.HttpClient = request.ThisClient; + + // This processes the ongoing data stream + Crestron.SimplSharp.CrestronIO.IAsyncResult asyncResult = null; + do + { + asyncResult = streamResponse.BeginRead(asyncState.BufferRead, 0, RequestState.BUFFER_SIZE, + new Crestron.SimplSharp.CrestronIO.AsyncCallback(ReadCallBack), asyncState); + } + while (asyncResult.CompletedSynchronously && !asyncState.Done); + + //Console.WriteLine("\r\nExit Response Callback\r\n"); + } + catch (Exception e) + { + ErrorLog.Notice("Exception occured in GetSecureRequestStreamCallback(): " + e.ToString()); + } + } + + void DataConnection_OnBytesReceived(object sender, EventArgs e) + { + Debug.Console(1, this, "DataConnection OnBytesReceived Fired"); + } + + /// + /// + /// + /// + private void ReadCallBack(Crestron.SimplSharp.CrestronIO.IAsyncResult asyncResult) + { + //we are getting back everything here, so cast the state from the call + RequestState requestState = asyncResult.AsyncState as RequestState; + Stream responseStream = requestState.StreamResponse; + + int read = responseStream.EndRead(asyncResult); + // Read the HTML page and then print it to the console. + if (read > 0) + { + var bytes = requestState.BufferRead; + + var bytesHandler = BytesReceived; + if (bytesHandler != null) + bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); + var textHandler = TextReceived; + if (textHandler != null) + { + var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); + textHandler(this, new GenericCommMethodReceiveTextArgs(str)); + } + + //requestState.RequestData.Append(Encoding.ASCII.GetString(requestState.BufferRead, 0, read)); + //CrestronConsole.PrintLine(requestState.RequestData.ToString()); + + //clear the byte array buffer used. + Array.Clear(requestState.BufferRead, 0, requestState.BufferRead.Length); + + if (asyncResult.CompletedSynchronously) + { + return; + } + + Crestron.SimplSharp.CrestronIO.IAsyncResult asynchronousResult; + do + { + asynchronousResult = responseStream.BeginRead(requestState.BufferRead, 0, RequestState.BUFFER_SIZE, + new Crestron.SimplSharp.CrestronIO.AsyncCallback(ReadCallBack), requestState); + } + while (asynchronousResult.CompletedSynchronously && !requestState.Done); + } + else + { + requestState.Done = true; + } + } + } + + /// + /// Stores the state of the request + /// + public class RequestState + { + public const int BUFFER_SIZE = 10000; + public byte[] BufferRead; + public HttpClient HttpClient; + public HttpClientRequest Request; + public HttpClientResponse Response; + public Stream StreamResponse; + public bool Done; + + public RequestState() + { + BufferRead = new byte[BUFFER_SIZE]; + HttpClient = null; + Request = null; + Response = null; + StreamResponse = null; + Done = false; + } + } + + /// + /// Waithandle for main thread. + /// + public class StreamAsyncTest + { + public CEvent wait_for_response = new CEvent(true, false); + } +} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj b/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj index 619347b..431bbcb 100644 --- a/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj +++ b/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj @@ -64,6 +64,7 @@ + Code diff --git a/Pepperdash Core/Pepperdash Core/PepperDash_Core.projectinfo b/Pepperdash Core/Pepperdash Core/PepperDash_Core.projectinfo index 354ae33..9305589 100644 Binary files a/Pepperdash Core/Pepperdash Core/PepperDash_Core.projectinfo and b/Pepperdash Core/Pepperdash Core/PepperDash_Core.projectinfo differ