mirror of
https://github.com/PepperDash/PepperDashCore.git
synced 2026-01-30 12:54:46 +00:00
Merge pull request #7 in PEC/pepperdash-simplsharp-core from feature/sseclient to master
* commit '208e2363083f9d7812a3cd9ea8fadc6aabe0893d': Updates to GenericHttpSseClient class to implement new iCommunicationReceiver interface - Added GenericHttpSseClient for use with Node Server
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -30,7 +30,7 @@ namespace PepperDash.Core
|
||||
/// <summary>
|
||||
/// The communication port that this gathers on
|
||||
/// </summary>
|
||||
public IBasicCommunication Port { get; private set; }
|
||||
public ICommunicationReceiver Port { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Default false. If true, the delimiter will be included in the line output
|
||||
@@ -55,7 +55,7 @@ namespace PepperDash.Core
|
||||
/// </summary>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="delimiter"></param>
|
||||
public CommunicationGather(IBasicCommunication port, char delimiter)
|
||||
public CommunicationGather(ICommunicationReceiver port, char delimiter)
|
||||
{
|
||||
Port = port;
|
||||
Delimiter = delimiter;
|
||||
@@ -67,7 +67,7 @@ namespace PepperDash.Core
|
||||
/// </summary>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="delimiter"></param>
|
||||
public CommunicationGather(IBasicCommunication port, string delimiter)
|
||||
public CommunicationGather(ICommunicationReceiver port, string delimiter)
|
||||
{
|
||||
Port = port;
|
||||
StringDelimiter = delimiter;
|
||||
|
||||
254
Pepperdash Core/Pepperdash Core/Comm/GenericHttpSseClient.cs
Normal file
254
Pepperdash Core/Pepperdash Core/Comm/GenericHttpSseClient.cs
Normal file
@@ -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<GenericCommMethodReceiveBytesArgs> BytesReceived;
|
||||
public event EventHandler<GenericCommMethodReceiveTextArgs> 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());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="asynchronousResult"></param>
|
||||
/// <param name="error"></param>
|
||||
/// <param name="status"></param>
|
||||
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");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="asyncResult"></param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores the state of the request
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waithandle for main thread.
|
||||
/// </summary>
|
||||
public class StreamAsyncTest
|
||||
{
|
||||
public CEvent wait_for_response = new CEvent(true, false);
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="CommunicationExtras.cs" />
|
||||
<Compile Include="Comm\ControlPropertiesConfig.cs" />
|
||||
<Compile Include="Comm\GenericHttpSseClient.cs" />
|
||||
<Compile Include="Comm\GenericSecureTcpIpServer.cs" />
|
||||
<Compile Include="Comm\GenericSecureTcpIpClient.cs">
|
||||
<SubType>Code</SubType>
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user