diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericUdpServer.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericUdpServer.cs index c462e3e..aba628e 100644 --- a/Pepperdash Core/Pepperdash Core/Comm/GenericUdpServer.cs +++ b/Pepperdash Core/Pepperdash Core/Comm/GenericUdpServer.cs @@ -1,240 +1,301 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; - -using Crestron.SimplSharp; -using Crestron.SimplSharp.CrestronSockets; - -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - - -namespace PepperDash.Core -{ - public class GenericUdpServer : Device, IBasicCommunication - { - /// - /// - /// - public event EventHandler BytesReceived; - - /// - /// - /// - public event EventHandler TextReceived; - - /// - /// - /// - //public event GenericSocketStatusChangeEventDelegate SocketStatusChange; - public event EventHandler ConnectionChange; - - public SocketStatus ClientStatus - { - get - { - return Server.ServerStatus; - } - } - - /// - /// Address of server - /// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronSockets; + +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + + + + +namespace PepperDash.Core +{ + public class GenericUdpServer : Device, IBasicCommunication + { + /// + /// + /// + public event EventHandler BytesReceived; + + /// + /// + /// + public event EventHandler TextReceived; + public event EventHandler DataRecievedExtra; + private CrestronQueue MessageQueue; + + /// + /// + /// + //public event GenericSocketStatusChangeEventDelegate SocketStatusChange; + public event EventHandler ConnectionChange; + + public SocketStatus ClientStatus + { + get + { + return Server.ServerStatus; + } + } + + + CCriticalSection DequeueLock; + /// + /// Address of server + /// public string Hostname { get; set; } /// /// IP Address of the sender of the last recieved message /// - public string LastMessageReceivedFrom + + + /// + /// Port on server + /// + public int Port { get; set; } + + /// + /// Another damn S+ helper because S+ seems to treat large port nums as signed ints + /// which screws up things + /// + public ushort UPort + { + get { return Convert.ToUInt16(Port); } + set { Port = Convert.ToInt32(value); } + } + + /// + /// Indicates that the UDP Server is enabled + /// + public bool IsConnected + { + get; + private set; + } + + /// + /// Defaults to 2000 + /// + public int BufferSize { get; set; } + + public UDPServer Server { get; private set; } + + public GenericUdpServer(string key, string address, int port, int buffefSize) + : base(key) + { + Hostname = address; + Port = port; + BufferSize = buffefSize; + + DequeueLock = new CCriticalSection(); + MessageQueue = new CrestronQueue(); + + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler); + } + + void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs) + { + // Re-enable the server if the link comes back up and the status should be connected + if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp + && IsConnected) + { + Connect(); + } + } + + void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + if (programEventType == eProgramStatusEventType.Stopping) + { + Debug.Console(1, this, "Program stopping. Disabling Server"); + Disconnect(); + } + } + + /// + /// Enables the UDP Server + /// + public void Connect() + { + if (Server == null) + { + Server = new UDPServer(); + + } + + if (string.IsNullOrEmpty(Hostname)) + { + Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericUdpServer '{0}': No address set", Key); + return; + } + if (Port < 1 || Port > 65535) + { + { + Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericUdpServer '{0}': Invalid port", Key); + return; + } + } + + var status = Server.EnableUDPServer(Hostname, Port); + + Debug.Console(2, this, "SocketErrorCode: {0}", status); + if (status == SocketErrorCodes.SOCKET_OK) + IsConnected = true; + + // Start receiving data + Server.ReceiveDataAsync(Receive); + } + + /// + /// Disabled the UDP Server + /// + public void Disconnect() + { + if(Server != null) + Server.DisableUDPServer(); + + IsConnected = false; + } + + + /// + /// Recursive method to receive data + /// + /// + /// + void Receive(UDPServer server, int numBytes) + { + Debug.Console(2, this, "Received {0} bytes", numBytes); + + if (numBytes > 0) + { + var sourceIp = Server.IPAddressLastMessageReceivedFrom; + var sourcePort = Server.IPPortLastMessageReceivedFrom; + 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()); + var bytesHandler = BytesReceived; + if (bytesHandler != null) + bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); + else + Debug.Console(2, this, "bytesHandler is null"); + var textHandler = TextReceived; + if (textHandler != null) + { + + Debug.Console(2, this, "RX: {0}", str); + textHandler(this, new GenericCommMethodReceiveTextArgs(str)); + } + else + Debug.Console(2, this, "textHandler is null"); + } + server.ReceiveDataAsync(Receive); + CrestronInvoke.BeginInvoke(DequeueEvent); + } + + void DequeueEvent(object notUsed) { - get { return Server.IPAddressLastMessageReceivedFrom; } - - } - - /// - /// Port on server - /// - public int Port { get; set; } - - /// - /// Another damn S+ helper because S+ seems to treat large port nums as signed ints - /// which screws up things - /// - public ushort UPort - { - get { return Convert.ToUInt16(Port); } - set { Port = Convert.ToInt32(value); } - } - - /// - /// Indicates that the UDP Server is enabled - /// - public bool IsConnected - { - get; - private set; - } - - /// - /// Defaults to 2000 - /// - public int BufferSize { get; set; } - - public UDPServer Server { get; private set; } - - public GenericUdpServer(string key, string address, int port, int buffefSize) - : base(key) - { - Hostname = address; - Port = port; - BufferSize = buffefSize; - - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler); - } - - void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs) - { - // Re-enable the server if the link comes back up and the status should be connected - if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp - && IsConnected) - { - Connect(); - } - } - - void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) - { - if (programEventType == eProgramStatusEventType.Stopping) - { - Debug.Console(1, this, "Program stopping. Disabling Server"); - Disconnect(); - } - } - - /// - /// Enables the UDP Server - /// - public void Connect() - { - if (Server == null) - { - Server = new UDPServer(); - - } - - if (string.IsNullOrEmpty(Hostname)) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericUdpServer '{0}': No address set", Key); - return; - } - if (Port < 1 || Port > 65535) - { - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericUdpServer '{0}': Invalid port", Key); - return; - } - } - - var status = Server.EnableUDPServer(Hostname, Port); - - Debug.Console(2, this, "SocketErrorCode: {0}", status); - if (status == SocketErrorCodes.SOCKET_OK) - IsConnected = true; - - // Start receiving data - Server.ReceiveDataAsync(Receive); - } - - /// - /// Disabled the UDP Server - /// - public void Disconnect() - { - if(Server != null) - Server.DisableUDPServer(); - - IsConnected = false; - } - - - /// - /// Recursive method to receive data - /// - /// - /// - void Receive(UDPServer server, int numBytes) - { - Debug.Console(2, this, "Received {0} bytes", numBytes); - - if (numBytes > 0) - { - var bytes = server.IncomingDataBuffer.Take(numBytes).ToArray(); - - Debug.Console(2, this, "Bytes: {0}", bytes.ToString()); - var bytesHandler = BytesReceived; - if (bytesHandler != null) - bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); - else - Debug.Console(2, this, "bytesHandler is null"); - var textHandler = TextReceived; - if (textHandler != null) - { - var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); - Debug.Console(2, this, "RX: {0}", str); - textHandler(this, new GenericCommMethodReceiveTextArgs(str)); - } - else - Debug.Console(2, this, "textHandler is null"); - } - server.ReceiveDataAsync(Receive); - } - - /// - /// General send method - /// - /// - public void SendText(string text) - { - var bytes = Encoding.GetEncoding(28591).GetBytes(text); - - if (IsConnected && Server != null) - { - Debug.Console(2, this, "TX: {0}", text); - Server.SendData(bytes, bytes.Length); - } - } - - public void SendBytes(byte[] bytes) - { - //if (Debug.Level == 2) - // Debug.Console(2, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); - if (IsConnected && Server != null) - Server.SendData(bytes, bytes.Length); - } - - - - } - - public class UdpServerPropertiesConfig - { - [JsonProperty(Required = Required.Always)] - public string Address { get; set; } - - [JsonProperty(Required = Required.Always)] - public int Port { get; set; } - - /// - /// Defaults to 32768 - /// - public int BufferSize { get; set; } - - public UdpServerPropertiesConfig() - { - BufferSize = 32768; - } - } + try + { + // Add CCritical Section + DequeueLock.TryEnter(); + while (!MessageQueue.IsEmpty) + { + // Pull from Queue and fire an event. + var Message = MessageQueue.TryToDequeue(); + var dataRecivedExtra = DataRecievedExtra; + if (dataRecivedExtra != null) + { + dataRecivedExtra(this, Message); + } + + + } + + } + catch (Exception e) + { + Debug.Console(0, "GenericUdpServer DequeueEvent error: {0}\r", e); + } + finally + { + DequeueLock.Leave(); + } + } + + /// + /// General send method + /// + /// + public void SendText(string text) + { + var bytes = Encoding.GetEncoding(28591).GetBytes(text); + + if (IsConnected && Server != null) + { + Debug.Console(2, this, "TX: {0}", text); + Server.SendData(bytes, bytes.Length); + } + } + + public void SendBytes(byte[] bytes) + { + //if (Debug.Level == 2) + // Debug.Console(2, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); + if (IsConnected && Server != null) + 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; + } + + /// + /// Stupid S+ Constructor + /// + public GenericUdpReceiveTextExtraArgs() { } + } + + public class UdpServerPropertiesConfig + { + [JsonProperty(Required = Required.Always)] + public string Address { get; set; } + + [JsonProperty(Required = Required.Always)] + public int Port { get; set; } + + /// + /// Defaults to 32768 + /// + public int BufferSize { get; set; } + + public UdpServerPropertiesConfig() + { + BufferSize = 32768; + } + } } \ No newline at end of file