diff --git a/src/PepperDash.Core/Comm/eControlMethods.cs b/src/PepperDash.Core/Comm/eControlMethods.cs
index 28a95b12..695594a1 100644
--- a/src/PepperDash.Core/Comm/eControlMethods.cs
+++ b/src/PepperDash.Core/Comm/eControlMethods.cs
@@ -74,6 +74,10 @@ namespace PepperDash.Core
///
/// Secure TCP/IP
///
- SecureTcpIp
+ SecureTcpIp,
+ ///
+ /// Used when comms needs to be handled in SIMPL and bridged opposite the normal direction
+ ///
+ ComBridge
}
}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Bridges/IBridge.cs b/src/PepperDash.Essentials.Core/Bridges/IBridge.cs
index 6e921921..34c11171 100644
--- a/src/PepperDash.Essentials.Core/Bridges/IBridge.cs
+++ b/src/PepperDash.Essentials.Core/Bridges/IBridge.cs
@@ -7,6 +7,13 @@ namespace PepperDash.Essentials.Core.Bridges
///
public interface IBridgeAdvanced
{
+ ///
+ /// Links the bridge to the API using the provided trilist, join start, join map key, and bridge.
+ ///
+ /// The trilist to link to.
+ /// The starting join number.
+ /// The key for the join map.
+ /// The EISC API bridge.
void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge);
}
}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Comm and IR/CommBridge.cs b/src/PepperDash.Essentials.Core/Comm and IR/CommBridge.cs
new file mode 100644
index 00000000..b93a8212
--- /dev/null
+++ b/src/PepperDash.Essentials.Core/Comm and IR/CommBridge.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Crestron.SimplSharp.CrestronSockets;
+using Crestron.SimplSharpPro.DeviceSupport;
+using Newtonsoft.Json;
+using PepperDash.Core;
+using PepperDash.Core.Logging;
+using PepperDash.Essentials.Core.Bridges;
+using PepperDash.Essentials.Core.Config;
+using PepperDash.Essentials.Core.Devices;
+
+
+namespace PepperDash.Essentials.Core
+{
+ ///
+ /// Implements IBasicCommunication and sends all communication through an EISC
+ ///
+ [Description("Generic communication wrapper class for any IBasicCommunication type")]
+ public class CommBridge : EssentialsBridgeableDevice, IBasicCommunication
+ {
+ private EiscApiAdvanced eisc;
+
+ private IBasicCommunicationJoinMap joinMap;
+
+ ///
+ /// Event triggered when text is received through the communication bridge.
+ ///
+ public event EventHandler TextReceived;
+
+ ///
+ /// Event triggered when bytes are received through the communication bridge.
+ ///
+ public event EventHandler BytesReceived;
+
+ ///
+ /// Indicates whether the communication bridge is currently connected.
+ ///
+ public bool IsConnected { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The unique key for the communication bridge.
+ /// The display name for the communication bridge.
+ public CommBridge(string key, string name)
+ : base(key, name)
+ {
+
+ }
+
+ ///
+ /// Sends a byte array through the communication bridge.
+ ///
+ /// The byte array to send.
+ public void SendBytes(byte[] bytes)
+ {
+ if (eisc == null)
+ {
+ this.LogWarning("EISC is null, cannot send bytes.");
+ return;
+ }
+ eisc.Eisc.SetString(joinMap.SendText.JoinNumber, Encoding.ASCII.GetString(bytes, 0, bytes.Length));
+ }
+
+ ///
+ /// Sends a text string through the communication bridge.
+ ///
+ /// The text string to send.
+ public void SendText(string text)
+ {
+ if (eisc == null)
+ {
+ this.LogWarning("EISC is null, cannot send text.");
+ return;
+ }
+ eisc.Eisc.SetString(joinMap.SendText.JoinNumber, text);
+ }
+
+ ///
+ /// Initiates a connection through the communication bridge.
+ ///
+ public void Connect()
+ {
+ if (eisc == null)
+ {
+ this.LogWarning("EISC is null, cannot connect.");
+ return;
+ }
+ eisc.Eisc.SetBool(joinMap.Connect.JoinNumber, true);
+ }
+
+ ///
+ /// Terminates the connection through the communication bridge.
+ ///
+ public void Disconnect()
+ {
+ if (eisc == null)
+ {
+ this.LogWarning("EISC is null, cannot disconnect.");
+ return;
+ }
+ eisc.Eisc.SetBool(joinMap.Connect.JoinNumber, false);
+ }
+
+ ///
+ public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
+ {
+ joinMap = new IBasicCommunicationJoinMap(joinStart);
+
+ var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
+
+ if (!string.IsNullOrEmpty(joinMapSerialized))
+ joinMap = JsonConvert.DeserializeObject(joinMapSerialized);
+
+ if (bridge != null)
+ {
+ bridge.AddJoinMap(Key, joinMap);
+ }
+ else
+ {
+ this.LogWarning("Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
+ }
+
+ this.LogDebug("Linking to Trilist '{0}'", trilist.ID.ToString("X"));
+
+ eisc = bridge;
+
+ trilist.SetBoolSigAction(joinMap.Connected.JoinNumber, (b) => IsConnected = b);
+
+ trilist.SetStringSigAction(joinMap.TextReceived.JoinNumber, (s) =>
+ {
+ TextReceived?.Invoke(this, new GenericCommMethodReceiveTextArgs(s));
+ BytesReceived?.Invoke(this, new GenericCommMethodReceiveBytesArgs(Encoding.ASCII.GetBytes(s)));
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs b/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs
index 2cd81a77..a0723c4b 100644
--- a/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs
+++ b/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs
@@ -1,11 +1,9 @@
using System;
-using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DM;
using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
@@ -38,9 +36,9 @@ namespace PepperDash.Essentials.Core
/// Returns a comm method of either com port, TCP, SSH, and puts this into the DeviceManager
///
/// The Device config object
- ///
- /// CreateCommForDevice method
- ///
+ ///
+ /// CreateCommForDevice method
+ ///
public static IBasicCommunication CreateCommForDevice(DeviceConfig deviceConfig)
{
EssentialsControlPropertiesConfig controlConfig = GetControlPropertiesConfig(deviceConfig);
@@ -56,35 +54,38 @@ namespace PepperDash.Essentials.Core
case eControlMethod.Com:
comm = new ComPortController(deviceConfig.Key + "-com", GetComPort, controlConfig.ComParams.Value, controlConfig);
break;
- case eControlMethod.Cec:
- comm = new CecPortController(deviceConfig.Key + "-cec", GetCecPort, controlConfig);
- break;
+ case eControlMethod.ComBridge:
+ comm = new CommBridge(deviceConfig.Key + "-simpl", deviceConfig.Name + " Simpl");
+ break;
+ case eControlMethod.Cec:
+ comm = new CecPortController(deviceConfig.Key + "-cec", GetCecPort, controlConfig);
+ break;
case eControlMethod.IR:
break;
- case eControlMethod.Ssh:
- {
- var ssh = new GenericSshClient(deviceConfig.Key + "-ssh", c.Address, c.Port, c.Username, c.Password);
- ssh.AutoReconnect = c.AutoReconnect;
- if(ssh.AutoReconnect)
- ssh.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
- comm = ssh;
- break;
- }
- case eControlMethod.Tcpip:
- {
- var tcp = new GenericTcpIpClient(deviceConfig.Key + "-tcp", c.Address, c.Port, c.BufferSize);
- tcp.AutoReconnect = c.AutoReconnect;
- if (tcp.AutoReconnect)
- tcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
- comm = tcp;
- break;
- }
- case eControlMethod.Udp:
- {
- var udp = new GenericUdpServer(deviceConfig.Key + "-udp", c.Address, c.Port, c.BufferSize);
- comm = udp;
- break;
- }
+ case eControlMethod.Ssh:
+ {
+ var ssh = new GenericSshClient(deviceConfig.Key + "-ssh", c.Address, c.Port, c.Username, c.Password);
+ ssh.AutoReconnect = c.AutoReconnect;
+ if (ssh.AutoReconnect)
+ ssh.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
+ comm = ssh;
+ break;
+ }
+ case eControlMethod.Tcpip:
+ {
+ var tcp = new GenericTcpIpClient(deviceConfig.Key + "-tcp", c.Address, c.Port, c.BufferSize);
+ tcp.AutoReconnect = c.AutoReconnect;
+ if (tcp.AutoReconnect)
+ tcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
+ comm = tcp;
+ break;
+ }
+ case eControlMethod.Udp:
+ {
+ var udp = new GenericUdpServer(deviceConfig.Key + "-udp", c.Address, c.Port, c.BufferSize);
+ comm = udp;
+ break;
+ }
case eControlMethod.Telnet:
break;
case eControlMethod.SecureTcpIp:
@@ -98,7 +99,7 @@ namespace PepperDash.Essentials.Core
}
default:
break;
- }
+ }
}
catch (Exception e)
{
@@ -107,15 +108,14 @@ namespace PepperDash.Essentials.Core
}
// put it in the device manager if it's the right flavor
- var comDev = comm as Device;
- if (comDev != null)
+ if (comm is Device comDev)
DeviceManager.AddDevice(comDev);
return comm;
}
- ///
- /// GetComPort method
- ///
+ ///
+ /// GetComPort method
+ ///
public static ComPort GetComPort(EssentialsControlPropertiesConfig config)
{
var comPar = config.ComParams;
@@ -126,74 +126,74 @@ namespace PepperDash.Essentials.Core
return null;
}
- ///
- /// Gets an ICec port from a RoutingInput or RoutingOutput on a device
- ///
- ///
- ///
- ///
- /// GetCecPort method
- ///
- public static ICec GetCecPort(ControlPropertiesConfig config)
- {
- try
- {
- var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey);
+ ///
+ /// Gets an ICec port from a RoutingInput or RoutingOutput on a device
+ ///
+ ///
+ ///
+ ///
+ /// GetCecPort method
+ ///
+ public static ICec GetCecPort(ControlPropertiesConfig config)
+ {
+ try
+ {
+ var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey);
- Debug.LogMessage(LogEventLevel.Information, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null
- ? "is not valid, failed to get cec port"
- : "found in device manager, attempting to get cec port");
+ Debug.LogMessage(LogEventLevel.Information, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null
+ ? "is not valid, failed to get cec port"
+ : "found in device manager, attempting to get cec port");
- if (dev == null)
- return null;
+ if (dev == null)
+ return null;
- if (String.IsNullOrEmpty(config.ControlPortName))
- {
- Debug.LogMessage(LogEventLevel.Information, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey);
- return null;
- }
+ if (String.IsNullOrEmpty(config.ControlPortName))
+ {
+ Debug.LogMessage(LogEventLevel.Information, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey);
+ return null;
+ }
- var inputsOutputs = dev as IRoutingInputsOutputs;
- if (inputsOutputs == null)
- {
+ var inputsOutputs = dev as IRoutingInputsOutputs;
+ if (inputsOutputs == null)
+ {
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: Device '{0}' does not support IRoutingInputsOutputs, failed to get CEC port called '{1}'",
config.ControlPortDevKey, config.ControlPortName);
- return null;
- }
+ return null;
+ }
var inputPort = inputsOutputs.InputPorts[config.ControlPortName];
- if (inputPort != null && inputPort.Port is ICec)
+ if (inputPort != null && inputPort.Port is ICec)
return inputPort.Port as ICec;
-
- var outputPort = inputsOutputs.OutputPorts[config.ControlPortName];
- if (outputPort != null && outputPort.Port is ICec)
- return outputPort.Port as ICec;
- }
- catch (Exception ex)
- {
- Debug.LogMessage(LogEventLevel.Debug, "GetCecPort Exception Message: {0}", ex.Message);
- Debug.LogMessage(LogEventLevel.Verbose, "GetCecPort Exception StackTrace: {0}", ex.StackTrace);
- if (ex.InnerException != null)
- Debug.LogMessage(LogEventLevel.Information, "GetCecPort Exception InnerException: {0}", ex.InnerException);
- }
+
+ var outputPort = inputsOutputs.OutputPorts[config.ControlPortName];
+ if (outputPort != null && outputPort.Port is ICec)
+ return outputPort.Port as ICec;
+ }
+ catch (Exception ex)
+ {
+ Debug.LogMessage(LogEventLevel.Debug, "GetCecPort Exception Message: {0}", ex.Message);
+ Debug.LogMessage(LogEventLevel.Verbose, "GetCecPort Exception StackTrace: {0}", ex.StackTrace);
+ if (ex.InnerException != null)
+ Debug.LogMessage(LogEventLevel.Information, "GetCecPort Exception InnerException: {0}", ex.InnerException);
+ }
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: Device '{0}' does not have a CEC port called '{1}'",
config.ControlPortDevKey, config.ControlPortName);
return null;
- }
+ }
///
/// Helper to grab the IComPorts device for this PortDeviceKey. Key "controlSystem" will
/// return the ControlSystem object from the Global class.
///
/// IComPorts device or null if the device is not found or does not implement IComPorts
- ///
- /// GetIComPortsDeviceFromManagedDevice method
- ///
+ ///
+ /// GetIComPortsDeviceFromManagedDevice method
+ ///
public static IComPorts GetIComPortsDeviceFromManagedDevice(string ComPortDevKey)
{
if ((ComPortDevKey.Equals("controlSystem", System.StringComparison.OrdinalIgnoreCase)
@@ -210,81 +210,81 @@ namespace PepperDash.Essentials.Core
}
}
- ///
- /// Represents a EssentialsControlPropertiesConfig
- ///
- public class EssentialsControlPropertiesConfig :
- ControlPropertiesConfig
- {
+ ///
+ /// Represents a EssentialsControlPropertiesConfig
+ ///
+ public class EssentialsControlPropertiesConfig :
+ ControlPropertiesConfig
+ {
- [JsonProperty("comParams", NullValueHandling = NullValueHandling.Ignore)]
- [JsonConverter(typeof(ComSpecJsonConverter))]
- public ComPort.ComPortSpec? ComParams { get; set; }
+ [JsonProperty("comParams", NullValueHandling = NullValueHandling.Ignore)]
+ [JsonConverter(typeof(ComSpecJsonConverter))]
+ public ComPort.ComPortSpec? ComParams { get; set; }
- [JsonProperty("cresnetId", NullValueHandling = NullValueHandling.Ignore)]
- public string CresnetId { get; set; }
+ [JsonProperty("cresnetId", NullValueHandling = NullValueHandling.Ignore)]
+ public string CresnetId { get; set; }
- ///
- /// Attempts to provide uint conversion of string CresnetId
- ///
- [JsonIgnore]
- public uint CresnetIdInt
- {
- get
- {
- try
- {
- return Convert.ToUInt32(CresnetId, 16);
- }
- catch (Exception)
- {
- throw new FormatException(string.Format("ERROR:Unable to convert Cresnet ID: {0} to hex. Error:\n{1}", CresnetId));
- }
- }
- }
+ ///
+ /// Attempts to provide uint conversion of string CresnetId
+ ///
+ [JsonIgnore]
+ public uint CresnetIdInt
+ {
+ get
+ {
+ try
+ {
+ return Convert.ToUInt32(CresnetId, 16);
+ }
+ catch (Exception)
+ {
+ throw new FormatException(string.Format("ERROR:Unable to convert Cresnet ID: {0} to hex. Error:\n{1}", CresnetId));
+ }
+ }
+ }
- [JsonProperty("infinetId", NullValueHandling = NullValueHandling.Ignore)]
- ///
- /// Gets or sets the InfinetId
- ///
- public string InfinetId { get; set; }
+ [JsonProperty("infinetId", NullValueHandling = NullValueHandling.Ignore)]
+ ///
+ /// Gets or sets the InfinetId
+ ///
+ public string InfinetId { get; set; }
- ///
- /// Attepmts to provide uiont conversion of string InifinetId
- ///
- [JsonIgnore]
- public uint InfinetIdInt
- {
- get
- {
- try
- {
- return Convert.ToUInt32(InfinetId, 16);
- }
- catch (Exception)
- {
- throw new FormatException(string.Format("ERROR:Unable to conver Infinet ID: {0} to hex. Error:\n{1}", InfinetId));
- }
- }
- }
- }
+ ///
+ /// Attepmts to provide uiont conversion of string InifinetId
+ ///
+ [JsonIgnore]
+ public uint InfinetIdInt
+ {
+ get
+ {
+ try
+ {
+ return Convert.ToUInt32(InfinetId, 16);
+ }
+ catch (Exception)
+ {
+ throw new FormatException(string.Format("ERROR:Unable to conver Infinet ID: {0} to hex. Error:\n{1}", InfinetId));
+ }
+ }
+ }
+ }
- ///
- /// Represents a IrControlSpec
- ///
- public class IrControlSpec
- {
- ///
- /// Gets or sets the PortDeviceKey
- ///
- public string PortDeviceKey { get; set; }
- ///
- /// Gets or sets the PortNumber
- ///
- public uint PortNumber { get; set; }
- ///
- /// Gets or sets the File
- ///
- public string File { get; set; }
- }
+ ///
+ /// Represents a IrControlSpec
+ ///
+ public class IrControlSpec
+ {
+ ///
+ /// Gets or sets the PortDeviceKey
+ ///
+ public string PortDeviceKey { get; set; }
+ ///
+ /// Gets or sets the PortNumber
+ ///
+ public uint PortNumber { get; set; }
+ ///
+ /// Gets or sets the File
+ ///
+ public string File { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Devices/EssentialsBridgeableDevice.cs b/src/PepperDash.Essentials.Core/Devices/EssentialsBridgeableDevice.cs
index 0812ca4e..0b1a5ff7 100644
--- a/src/PepperDash.Essentials.Core/Devices/EssentialsBridgeableDevice.cs
+++ b/src/PepperDash.Essentials.Core/Devices/EssentialsBridgeableDevice.cs
@@ -3,16 +3,29 @@ using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Core
{
- public abstract class EssentialsBridgeableDevice:EssentialsDevice, IBridgeAdvanced
+ ///
+ /// Base class for devices that can be bridged to an EISC API.
+ ///
+ public abstract class EssentialsBridgeableDevice : EssentialsDevice, IBridgeAdvanced
{
+ ///
+ /// Initializes a new instance of the class with the specified key.
+ ///
+ /// The unique key for the device.
protected EssentialsBridgeableDevice(string key) : base(key)
{
}
+ ///
+ /// Initializes a new instance of the class with the specified key and name.
+ ///
+ /// The unique key for the device.
+ /// The display name for the device.
protected EssentialsBridgeableDevice(string key, string name) : base(key, name)
{
}
+ ///
public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge);
}
}
\ No newline at end of file