diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs
index 9db81122..56b36791 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs
@@ -179,7 +179,7 @@ namespace PepperDash.Essentials.Core
{
public static eDeviceRegistrationUnRegistrationResponse RegisterWithLogging(this GenericBase device, string key)
{
- var result = device.Register();
+ var result = device.Register();
var level = result == eDeviceRegistrationUnRegistrationResponse.Success ?
Debug.ErrorLogLevel.Notice : Debug.ErrorLogLevel.Error;
Debug.Console(0, level, "Register device result: '{0}', type '{1}', result {2}", key, device, result);
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj
index 06978313..ae420105 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj
@@ -98,12 +98,12 @@
False
- ..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll
+ ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll
False
False
- ..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll
+ ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll
False
@@ -113,7 +113,7 @@
False
- ..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe
+ ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe
False
@@ -223,8 +223,12 @@
+
+
+
+
@@ -239,6 +243,7 @@
+
@@ -314,6 +319,7 @@
+
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/ComsMessage.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/ComsMessage.cs
new file mode 100644
index 00000000..92c97248
--- /dev/null
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/ComsMessage.cs
@@ -0,0 +1,73 @@
+using System;
+using PepperDash.Core;
+
+namespace PepperDash_Essentials_Core.Queues
+{
+ ///
+ /// IBasicCommunication Message for IQueue
+ ///
+ public class ComsMessage : IQueueMessage
+ {
+ private readonly byte[] _bytes;
+ private readonly IBasicCommunication _coms;
+ private readonly string _string;
+ private readonly bool _isByteMessage;
+
+ ///
+ /// Constructor for a string message
+ ///
+ /// IBasicCommunication to send the message
+ /// Message to send
+ public ComsMessage(IBasicCommunication coms, string message)
+ {
+ Validate(coms, message);
+ _coms = coms;
+ _string = message;
+ }
+
+ ///
+ /// Constructor for a byte message
+ ///
+ /// IBasicCommunication to send the message
+ /// Message to send
+ public ComsMessage(IBasicCommunication coms, byte[] message)
+ {
+ Validate(coms, message);
+ _coms = coms;
+ _bytes = message;
+ _isByteMessage = true;
+ }
+
+ private void Validate(IBasicCommunication coms, object message)
+ {
+ if (_coms == null)
+ throw new ArgumentNullException("coms");
+
+ if (message == null)
+ throw new ArgumentNullException("message");
+ }
+
+ ///
+ /// Dispatchs the string/byte[] to the IBasicCommunication specified
+ ///
+ public void Dispatch()
+ {
+ if (_isByteMessage)
+ {
+ _coms.SendBytes(_bytes);
+ }
+ else
+ {
+ _coms.SendText(_string);
+ }
+ }
+
+ ///
+ /// Shows either the byte[] or string to be sent
+ ///
+ public override string ToString()
+ {
+ return _bytes != null ? _bytes.ToString() : _string;
+ }
+ }
+}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs
new file mode 100644
index 00000000..1f27fe1e
--- /dev/null
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/GenericQueue.cs
@@ -0,0 +1,144 @@
+using System;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro.CrestronThread;
+using PepperDash.Core;
+
+namespace PepperDash_Essentials_Core.Queues
+{
+ ///
+ /// Threadsafe processing of queued items with pacing if required
+ ///
+ public class GenericQueue : IQueue
+ {
+ private readonly string _key;
+ protected readonly CrestronQueue _queue;
+ protected readonly Thread _worker;
+ protected readonly CEvent _waitHandle = new CEvent();
+
+ private readonly bool _delayEnabled;
+ private readonly int _delayTime;
+
+ ///
+ /// If the instance has been disposed.
+ ///
+ public bool Disposed { get; private set; }
+
+ ///
+ /// Constructor for generic queue with no pacing
+ ///
+ /// Key
+ public GenericQueue(string key)
+ {
+ _key = key;
+ _queue = new CrestronQueue();
+ _worker = new Thread(ProcessQueue, null, Thread.eThreadStartOptions.Running);
+
+ CrestronEnvironment.ProgramStatusEventHandler += programEvent =>
+ {
+ if (programEvent != eProgramStatusEventType.Stopping)
+ return;
+
+ Dispose();
+ };
+ }
+
+ ///
+ /// Constructor for generic queue with no pacing
+ ///
+ /// Key
+ /// Pacing in ms between actions
+ public GenericQueue(string key, int pacing)
+ : this(key)
+ {
+ _delayEnabled = pacing > 0;
+ _delayTime = pacing;
+ }
+
+ ///
+ /// Thread callback
+ ///
+ /// The action used to process dequeued items
+ /// Null when the thread is exited
+ private object ProcessQueue(object obj)
+ {
+ while (true)
+ {
+ IQueueMessage item = null;
+
+ if (_queue.Count > 0)
+ {
+ item = _queue.Dequeue();
+ if (item == null)
+ break;
+ }
+ if (item != null)
+ {
+ try
+ {
+ Debug.Console(2, this, "Processing queue item: '{0}'", item.ToString());
+ item.Dispatch();
+
+ if (_delayEnabled)
+ Thread.Sleep(_delayTime);
+ }
+ catch (Exception ex)
+ {
+ Debug.ConsoleWithLog(0, this, "Caught an exception in the Queue {0}\r{1}\r{2}", ex.Message, ex.InnerException, ex.StackTrace);
+ }
+ }
+ else _waitHandle.Wait();
+ }
+
+ return null;
+ }
+
+ public void Enqueue(IQueueMessage item)
+ {
+ _queue.Enqueue(item);
+ _waitHandle.Set();
+ }
+
+ ///
+ /// Disposes the thread and cleans up resources. Thread cannot be restarted once
+ /// disposed.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ CrestronEnvironment.GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Actually does the disposing. If you override this method, be sure to either call the base implementation
+ /// or clean up all the resources yourself.
+ ///
+ /// set to true unless called from finalizer
+ protected void Dispose(bool disposing)
+ {
+ if (Disposed)
+ return;
+
+ if (disposing)
+ {
+ Enqueue(null);
+ _worker.Join();
+ _waitHandle.Close();
+ }
+
+ Disposed = true;
+ }
+
+ ~GenericQueue()
+ {
+ Dispose(false);
+ }
+
+ ///
+ /// Key
+ ///
+ public string Key
+ {
+ get { return _key; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/IQueue.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/IQueue.cs
new file mode 100644
index 00000000..852542d5
--- /dev/null
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/IQueue.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using PepperDash.Core;
+
+namespace PepperDash_Essentials_Core.Queues
+{
+ public interface IQueue : IKeyed, IDisposable where T : class
+ {
+ void Enqueue(T item);
+ bool Disposed { get; }
+ }
+}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/IQueueMessage.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/IQueueMessage.cs
new file mode 100644
index 00000000..ee0d87d2
--- /dev/null
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/IQueueMessage.cs
@@ -0,0 +1,7 @@
+namespace PepperDash_Essentials_Core.Queues
+{
+ public interface IQueueMessage
+ {
+ void Dispatch();
+ }
+}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/ProcessStringMessage.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/ProcessStringMessage.cs
new file mode 100644
index 00000000..a15f7231
--- /dev/null
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/ProcessStringMessage.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace PepperDash_Essentials_Core.Queues
+{
+ ///
+ /// Message class for processing strings via an IQueue
+ ///
+ public class ProcessStringMessage : IQueueMessage
+ {
+ private readonly Action _action;
+ private readonly string _message;
+
+ ///
+ /// Constructor
+ ///
+ /// Message to be processed
+ /// Action to invoke on the message
+ public ProcessStringMessage(string message, Action action)
+ {
+ _message = message;
+ _action = action;
+ }
+
+ ///
+ /// Processes the string with the given action
+ ///
+ public void Dispatch()
+ {
+ if (_action == null || String.IsNullOrEmpty(_message))
+ return;
+
+ _action(_message);
+ }
+
+ ///
+ /// To string
+ ///
+ /// The current message
+ public override string ToString()
+ {
+ return _message ?? String.Empty;
+ }
+ }
+}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/StringResponseProcessor.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/StringResponseProcessor.cs
new file mode 100644
index 00000000..7f6477a3
--- /dev/null
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Queues/StringResponseProcessor.cs
@@ -0,0 +1,106 @@
+using System;
+using Crestron.SimplSharp;
+using PepperDash.Core;
+
+namespace PepperDash_Essentials_Core.Queues
+{
+ public sealed class StringResponseProcessor : IKeyed, IDisposable
+ {
+ private readonly Action _processStringAction;
+ private readonly IQueue _queue;
+ private readonly IBasicCommunication _coms;
+ private readonly CommunicationGather _gather;
+
+ private StringResponseProcessor(string key, Action processStringAction)
+ {
+ _processStringAction = processStringAction;
+ _queue = new GenericQueue(key);
+
+ CrestronEnvironment.ProgramStatusEventHandler += programEvent =>
+ {
+ if (programEvent != eProgramStatusEventType.Stopping)
+ return;
+
+ Dispose();
+ };
+ }
+
+ ///
+ /// Constructor that builds an instance and subscribes to coms TextReceived for processing
+ ///
+ /// Com port to process strings from
+ /// Action to process the incoming strings
+ public StringResponseProcessor(IBasicCommunication coms, Action processStringAction)
+ : this(coms.Key, processStringAction)
+ {
+ _coms = coms;
+ coms.TextReceived += OnResponseReceived;
+ }
+
+ ///
+ /// Constructor that builds an instance and subscribes to gather Line Received for processing
+ ///
+ /// Gather to process strings from
+ /// Action to process the incoming strings
+ public StringResponseProcessor(CommunicationGather gather, Action processStringAction)
+ : this(gather.Port.Key, processStringAction)
+ {
+ _gather = gather;
+ gather.LineReceived += OnResponseReceived;
+ }
+
+ private void OnResponseReceived(object sender, GenericCommMethodReceiveTextArgs args)
+ {
+ _queue.Enqueue(new ProcessStringMessage(args.Text, _processStringAction));
+ }
+
+ ///
+ /// Key
+ ///
+ public string Key
+ {
+ get { return _queue.Key; }
+ }
+
+ ///
+ /// Disposes the instance and cleans up resources.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ CrestronEnvironment.GC.SuppressFinalize(this);
+ }
+
+ private void Dispose(bool disposing)
+ {
+ if (Disposed)
+ return;
+
+ if (disposing)
+ {
+ if (_coms != null)
+ _coms.TextReceived -= OnResponseReceived;
+
+ if (_gather != null)
+ {
+ _gather.LineReceived -= OnResponseReceived;
+ _gather.Stop();
+ }
+
+ _queue.Dispose();
+ }
+
+ Disposed = true;
+ }
+
+ ///
+ /// If the instance has been disposed or not. If it has, you can not use it anymore
+ ///
+ public bool Disposed { get; private set; }
+
+ ~StringResponseProcessor()
+ {
+ Dispose(false);
+ }
+ }
+}
\ No newline at end of file
diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj
index a8843496..7c8b163a 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj
+++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj
@@ -68,12 +68,12 @@
False
- ..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll
+ ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll
False
False
- ..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll
+ ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll
False
@@ -83,7 +83,7 @@
False
- ..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe
+ ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe
False
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
index 00612bab..d18cb6ce 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
@@ -73,12 +73,12 @@
False
- ..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll
+ ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll
False
False
- ..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll
+ ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll
False
@@ -88,7 +88,7 @@
False
- ..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe
+ ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe
False