diff --git a/Pepperdash Core/Pepperdash Core/Comm/ControlPropertiesConfig.cs b/Pepperdash Core/Pepperdash Core/Comm/ControlPropertiesConfig.cs index 1759deb..c4e6a07 100644 --- a/Pepperdash Core/Pepperdash Core/Comm/ControlPropertiesConfig.cs +++ b/Pepperdash Core/Pepperdash Core/Comm/ControlPropertiesConfig.cs @@ -19,6 +19,9 @@ namespace PepperDash.Core [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] // In case "null" is present in config on this value public uint ControlPortNumber { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] // In case "null" is present in config on this value + public string ControlPortName { get; set; } + public TcpSshPropertiesConfig TcpSshProperties { get; set; } public string IrFile { get; set; } diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs index 4e0f871..65c428f 100644 --- a/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs +++ b/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs @@ -154,6 +154,8 @@ namespace PepperDash.Core BufferSize = bufferSize; AutoReconnectIntervalMs = 5000; + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + //if (string.IsNullOrEmpty(address)) //{ // Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericTcpIpClient '{0}': No address set", key); diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericUdpServer.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericUdpServer.cs new file mode 100644 index 0000000..a67a05f --- /dev/null +++ b/Pepperdash Core/Pepperdash Core/Comm/GenericUdpServer.cs @@ -0,0 +1,231 @@ +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 + /// + public string Hostname { get; set; } + + /// + /// 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; + } + } +} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/Comm/eControlMethods.cs b/Pepperdash Core/Pepperdash Core/Comm/eControlMethods.cs index d320366..d4a2028 100644 --- a/Pepperdash Core/Pepperdash Core/Comm/eControlMethods.cs +++ b/Pepperdash Core/Pepperdash Core/Comm/eControlMethods.cs @@ -8,6 +8,6 @@ namespace PepperDash.Core { public enum eControlMethod { - None = 0, Com, IpId, IpidTcp, IR, Ssh, Tcpip, Telnet, Cresnet + None = 0, Com, IpId, IpidTcp, IR, Ssh, Tcpip, Telnet, Cresnet, Cec, Udp } } \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/Device.cs b/Pepperdash Core/Pepperdash Core/Device.cs index 6f02fc4..7132f94 100644 --- a/Pepperdash Core/Pepperdash Core/Device.cs +++ b/Pepperdash Core/Pepperdash Core/Device.cs @@ -68,6 +68,12 @@ namespace PepperDash.Core _PostActivationActions.Add(act); } + public void PreActivate() + { + if (_PreActivationActions != null) + _PreActivationActions.ForEach(a => a.Invoke()); + } + /// /// Gets this device ready to be used in the system. Runs any added pre-activation items, and /// all post-activation at end. Classes needing additional logic to @@ -75,14 +81,20 @@ namespace PepperDash.Core /// public bool Activate() { - if (_PreActivationActions != null) - _PreActivationActions.ForEach(a => a.Invoke()); + //if (_PreActivationActions != null) + // _PreActivationActions.ForEach(a => a.Invoke()); var result = CustomActivate(); - if(result && _PostActivationActions != null) - _PostActivationActions.ForEach(a => a.Invoke()); + //if(result && _PostActivationActions != null) + // _PostActivationActions.ForEach(a => a.Invoke()); return result; } + public void PostActivate() + { + if (_PostActivationActions != null) + _PostActivationActions.ForEach(a => a.Invoke()); + } + /// /// Called in between Pre and PostActivationActions when Activate() is called. /// Override to provide addtitional setup when calling activation. Overriding classes diff --git a/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj b/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj index 38052fc..5e509c5 100644 --- a/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj +++ b/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj @@ -74,6 +74,7 @@ + diff --git a/Pepperdash Core/Pepperdash Core/Properties/AssemblyInfo.cs b/Pepperdash Core/Pepperdash Core/Properties/AssemblyInfo.cs index fabe661..f1c301a 100644 --- a/Pepperdash Core/Pepperdash Core/Properties/AssemblyInfo.cs +++ b/Pepperdash Core/Pepperdash Core/Properties/AssemblyInfo.cs @@ -4,4 +4,4 @@ [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Pepperdash_Core")] [assembly: AssemblyCopyright("Copyright © PepperDash 2016")] -[assembly: AssemblyVersion("1.0.9.*")] +[assembly: AssemblyVersion("1.0.11.*")]