Merged in bugfix/pdc-7 (pull request #10)

Bugfix/pdc 7

Approved-by: Neil Dorin <ndorin@pepperdash.com>
This commit is contained in:
Neil Dorin
2019-05-16 18:31:22 +00:00
committed by Heath Volmer
7 changed files with 318 additions and 235 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -174,8 +174,8 @@ namespace PepperDash.Core
if (Client != null) if (Client != null)
{ {
Debug.Console(1, this, "Program stopping. Closing connection"); Debug.Console(1, this, "Program stopping. Closing connection");
Client.Disconnect(); Disconnect();
Client.Dispose(); //Client.Dispose();
} }
} }
} }

View File

@@ -387,13 +387,16 @@ namespace PepperDash.Core
myTcpServer.SocketSendOrReceiveTimeOutInMs = (this.HeartbeatRequiredIntervalMs * 5); myTcpServer.SocketSendOrReceiveTimeOutInMs = (this.HeartbeatRequiredIntervalMs * 5);
// myTcpServer.HandshakeTimeout = 30; // myTcpServer.HandshakeTimeout = 30;
myTcpServer.SocketStatusChange += new TCPServerSocketStatusChangeEventHandler(TcpServer_SocketStatusChange);
} }
else else
{ {
KillServer(); KillServer();
myTcpServer.PortNumber = Port; myTcpServer.PortNumber = Port;
} }
myTcpServer.SocketStatusChange -= TcpServer_SocketStatusChange;
myTcpServer.SocketStatusChange += TcpServer_SocketStatusChange;
ServerStopped = false; ServerStopped = false;
myTcpServer.WaitForConnectionAsync(IPAddress.Any, TcpConnectCallback); myTcpServer.WaitForConnectionAsync(IPAddress.Any, TcpConnectCallback);
OnServerStateChange(myTcpServer.State); OnServerStateChange(myTcpServer.State);

View File

@@ -11,6 +11,8 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
namespace PepperDash.Core namespace PepperDash.Core
{ {
public class GenericUdpServer : Device, IBasicCommunication public class GenericUdpServer : Device, IBasicCommunication
@@ -25,6 +27,16 @@ namespace PepperDash.Core
/// </summary> /// </summary>
public event EventHandler<GenericCommMethodReceiveTextArgs> TextReceived; public event EventHandler<GenericCommMethodReceiveTextArgs> TextReceived;
/// <summary>
/// This event will fire when a message is dequeued that includes the source IP and Port info if needed to determine the source of the received data.
/// </summary>
public event EventHandler<GenericUdpReceiveTextExtraArgs> DataRecievedExtra;
/// <summary>
/// Queue to temporarily store received messages with the source IP and Port info
/// </summary>
private CrestronQueue<GenericUdpReceiveTextExtraArgs> MessageQueue;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
@@ -39,11 +51,18 @@ namespace PepperDash.Core
} }
} }
CCriticalSection DequeueLock;
/// <summary> /// <summary>
/// Address of server /// Address of server
/// </summary> /// </summary>
public string Hostname { get; set; } public string Hostname { get; set; }
/// <summary>
/// IP Address of the sender of the last recieved message
/// </summary>
/// <summary> /// <summary>
/// Port on server /// Port on server
/// </summary> /// </summary>
@@ -82,6 +101,9 @@ namespace PepperDash.Core
Port = port; Port = port;
BufferSize = buffefSize; BufferSize = buffefSize;
DequeueLock = new CCriticalSection();
MessageQueue = new CrestronQueue<GenericUdpReceiveTextExtraArgs>();
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler); CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
} }
@@ -162,7 +184,11 @@ namespace PepperDash.Core
if (numBytes > 0) if (numBytes > 0)
{ {
var sourceIp = Server.IPAddressLastMessageReceivedFrom;
var sourcePort = Server.IPPortLastMessageReceivedFrom;
var bytes = server.IncomingDataBuffer.Take(numBytes).ToArray(); var bytes = server.IncomingDataBuffer.Take(numBytes).ToArray();
var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length);
MessageQueue.TryToEnqueue(new GenericUdpReceiveTextExtraArgs(str, sourceIp, sourcePort, bytes));
Debug.Console(2, this, "Bytes: {0}", bytes.ToString()); Debug.Console(2, this, "Bytes: {0}", bytes.ToString());
var bytesHandler = BytesReceived; var bytesHandler = BytesReceived;
@@ -173,7 +199,7 @@ namespace PepperDash.Core
var textHandler = TextReceived; var textHandler = TextReceived;
if (textHandler != null) if (textHandler != null)
{ {
var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length);
Debug.Console(2, this, "RX: {0}", str); Debug.Console(2, this, "RX: {0}", str);
textHandler(this, new GenericCommMethodReceiveTextArgs(str)); textHandler(this, new GenericCommMethodReceiveTextArgs(str));
} }
@@ -181,6 +207,41 @@ namespace PepperDash.Core
Debug.Console(2, this, "textHandler is null"); Debug.Console(2, this, "textHandler is null");
} }
server.ReceiveDataAsync(Receive); server.ReceiveDataAsync(Receive);
// Attempt to enter the CCritical Secion and if we can, start the dequeue thread
var gotLock = DequeueLock.TryEnter();
if (gotLock)
CrestronInvoke.BeginInvoke((o) => DequeueEvent());
}
/// <summary>
/// This method gets spooled up in its own thread an protected by a CCriticalSection to prevent multiple threads from running concurrently.
/// It will dequeue items as they are enqueued automatically.
/// </summary>
void DequeueEvent()
{
try
{
while (true)
{
// Pull from Queue and fire an event. Block indefinitely until an item can be removed, similar to a Gather.
var message = MessageQueue.Dequeue();
var dataRecivedExtra = DataRecievedExtra;
if (dataRecivedExtra != null)
{
dataRecivedExtra(this, message);
}
}
}
catch (Exception e)
{
Debug.Console(0, "GenericUdpServer DequeueEvent error: {0}\r", e);
}
finally
{
// Make sure to leave the CCritical section in case an exception above stops this thread, or we won't be able to restart it.
DequeueLock.Leave();
}
} }
/// <summary> /// <summary>
@@ -206,8 +267,27 @@ namespace PepperDash.Core
Server.SendData(bytes, bytes.Length); Server.SendData(bytes, bytes.Length);
} }
}
public class GenericUdpReceiveTextExtraArgs : EventArgs
{
public string Text { get; private set; }
public string IpAddress { get; private set; }
public int Port { get; private set; }
public byte[] Bytes { get; private set; }
public GenericUdpReceiveTextExtraArgs(string text, string ipAddress, int port, byte[] bytes)
{
Text = text;
IpAddress = ipAddress;
Port = port;
Bytes = bytes;
}
/// <summary>
/// Stupid S+ Constructor
/// </summary>
public GenericUdpReceiveTextExtraArgs() { }
} }
public class UdpServerPropertiesConfig public class UdpServerPropertiesConfig

View File

@@ -59,7 +59,7 @@
</Reference> </Reference>
<Reference Include="SimplSharpReflectionInterface, Version=1.0.5583.25238, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL"> <Reference Include="SimplSharpReflectionInterface, Version=1.0.5583.25238, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath> <HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />

View File

@@ -4,4 +4,4 @@
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Pepperdash_Core")] [assembly: AssemblyProduct("Pepperdash_Core")]
[assembly: AssemblyCopyright("Copyright © PepperDash 2019")] [assembly: AssemblyCopyright("Copyright © PepperDash 2019")]
[assembly: AssemblyVersion("1.0.16.*")] [assembly: AssemblyVersion("1.0.17.*")]