diff --git a/PanoptoRRLightService/Kuando/BusylightSDK.dll b/PanoptoRRLightService/Kuando/BusylightSDK.dll
new file mode 100644
index 0000000..5ed32ce
Binary files /dev/null and b/PanoptoRRLightService/Kuando/BusylightSDK.dll differ
diff --git a/PanoptoRRLightService/Kuando/KuandoLight.cs b/PanoptoRRLightService/Kuando/KuandoLight.cs
new file mode 100644
index 0000000..5dbd5c5
--- /dev/null
+++ b/PanoptoRRLightService/Kuando/KuandoLight.cs
@@ -0,0 +1,231 @@
+using System;
+using System.Threading;
+using System.Diagnostics;
+using Busylight;
+
+namespace RRLightProgram
+{
+ class KuandoLight : ILightControl
+ {
+ #region variables
+
+ ///
+ /// Interface that can post events to a state machine.
+ /// Does nothing because Kuando Busylight has not input parameters
+ ///
+ private IStateMachine stateMachine;
+
+ ///
+ /// Controls light controls
+ ///
+ private KuandoLightWrapper wrapper;
+
+ ///
+ /// Event indicating the background threads should stop
+ ///
+ private ManualResetEvent stopRequested = new ManualResetEvent(initialState: false);
+
+ ///
+ /// Internal structure to carry the light control request.
+ ///
+ struct LightControlRequest
+ {
+ public LightColor Color;
+ public bool Flash;
+ };
+
+ ///
+ /// Latest request of light control. Older pending request is disposed by overwrite.
+ ///
+ private LightControlRequest? outstandingRequest = null;
+
+ ///
+ /// Lock to access outstandingRequest variable.
+ ///
+ private object outstandingRequestLock = new object();
+
+ ///
+ /// Event to be fired when a request is queued.
+ ///
+ private ManualResetEvent outstandingRequestExist = new ManualResetEvent(initialState: false);
+
+ ///
+ /// Background thread to process light control requests.
+ ///
+ private Thread processLightControlRequestsThread;
+
+ #endregion
+
+ #region Constructor, Initialize
+
+ ///
+ /// Constructor
+ ///
+ /// The state machine
+ public KuandoLight(IStateMachine stateMachine)
+ {
+ if (stateMachine == null)
+ {
+ throw new ArgumentException("stateMachine cannot be null.");
+ }
+ this.stateMachine = stateMachine;
+ }
+
+ ///
+ /// Start the kuando light service
+ ///
+ /// Whether the service was started successfully
+ public bool Start()
+ {
+ try
+ {
+ this.wrapper = new KuandoLightWrapper();
+ }
+ catch (ApplicationException e)
+ {
+ Trace.TraceError("Failed to initialize KuandoLightWrapper. {0}", e);
+ return false;
+ }
+
+ this.processLightControlRequestsThread = new Thread(ProcessLightControlRequestsLoop);
+ this.processLightControlRequestsThread.Start();
+
+ Trace.TraceInformation("started kuando light");
+ return true;
+ }
+
+ ///
+ /// Stop the Kuando light service
+ ///
+ public void Stop()
+ {
+ this.stopRequested.Set();
+ this.processLightControlRequestsThread.Join();
+
+ this.wrapper.Close();
+ }
+
+ #endregion
+
+
+ #region Light Control Logic
+
+ ///
+ /// Continue in a thread while the service is running and check for new LightControlRequests
+ ///
+ private void ProcessLightControlRequestsLoop()
+ {
+ while(true)
+ {
+ int indexFired = WaitHandle.WaitAny(new WaitHandle[] { this.stopRequested, this.outstandingRequestExist });
+
+ if (indexFired == 0)
+ {
+ // this.stopRequested fired. Exit the thread.
+ break;
+ }
+
+ LightControlRequest? request = null;
+ lock (this.outstandingRequestLock)
+ {
+ request = this.outstandingRequest;
+ this.outstandingRequest = null;
+ this.outstandingRequestExist.Reset();
+ }
+
+ if (!request.HasValue)
+ {
+ // Phantom event. Wait next.
+ continue;
+ }
+ Trace.TraceInformation("ProcessLightControlRequestsLoop processing: color={0}, flash={1}", request.Value.Color, request.Value.Flash);
+
+ BusylightColor color = ConvertColor(request.Value.Color);
+
+ if (request.Value.Flash)
+ {
+ wrapper.SetFlash(color);
+ }
+ else
+ {
+ wrapper.SetSolidLight(color);
+ }
+
+ }
+ }
+
+ ///
+ /// Convert a LightColor to a BusylightColor, which can be recognized by Kuando devices
+ ///
+ /// The LightColor input
+ /// The BusyLightColor corresponding to the input
+ private BusylightColor ConvertColor(LightColor inputColor)
+ {
+ BusylightColor result;
+
+ switch (inputColor)
+ {
+ case LightColor.Red:
+ result = BusylightColor.Red;
+ break;
+ case LightColor.Green:
+ result = BusylightColor.Green;
+ break;
+ case LightColor.Yellow:
+ result = BusylightColor.Yellow;
+ break;
+ case LightColor.Off:
+ result = BusylightColor.Off;
+ break;
+ default:
+ throw new ArgumentException("Unexpected inputColor");
+ }
+
+ return result;
+ }
+
+ #endregion
+
+ #region ILightControl
+
+ ///
+ /// Create a new request for the Kuando light to flash a given color.
+ ///
+ /// The color to flash on the light
+ public void SetFlash(LightColor color)
+ {
+ LightControlRequest request = new LightControlRequest()
+ {
+ Color = color,
+ Flash = true
+ };
+ lock (this.outstandingRequestLock)
+ {
+ outstandingRequest = request;
+ outstandingRequestExist.Set();
+ TraceVerbose.Trace("SetFlash({0}): request queued.", color);
+ }
+ }
+
+ ///
+ /// Set the Kuando light to be a solid color
+ ///
+ /// The color to set the light to
+ public void SetSolid(LightColor color)
+ {
+ LightControlRequest request = new LightControlRequest()
+ {
+ Color = color,
+ Flash = false
+ };
+ lock(this.outstandingRequestLock)
+ {
+ outstandingRequest = request;
+ outstandingRequestExist.Set();
+ TraceVerbose.Trace("SetSolid({0}): request queued.", color);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/PanoptoRRLightService/Kuando/KuandoLightWrapper.cs b/PanoptoRRLightService/Kuando/KuandoLightWrapper.cs
new file mode 100644
index 0000000..4a47788
--- /dev/null
+++ b/PanoptoRRLightService/Kuando/KuandoLightWrapper.cs
@@ -0,0 +1,82 @@
+using Busylight;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace RRLightProgram
+{
+ class KuandoLightWrapper
+ {
+ #region variables
+ ///
+ /// Kuando busylight object. Controls turning light on/off and color
+ ///
+ private Busylight.SDK busylight;
+
+ #endregion
+
+ #region Device Setup
+
+ ///
+ /// Constructor
+ ///
+ public KuandoLightWrapper()
+ {
+ this.busylight = new Busylight.SDK();
+ this.TurnOffAllLights();
+ }
+
+ ///
+ /// Close the wrapper and turn off lights
+ ///
+ public void Close()
+ {
+ this.TurnOffAllLights();
+
+ this.CloseDevice();
+ }
+
+ ///
+ /// Close Kuando device
+ ///
+ private void CloseDevice()
+ {
+ busylight.Terminate();
+ }
+
+ ///
+ /// Turn off the connected lights
+ ///
+ private void TurnOffAllLights()
+ {
+ busylight.Light(BusylightColor.Off);
+ }
+
+ #endregion
+
+ #region Light control
+
+ ///
+ /// Turn on the light as a solid color
+ ///
+ /// The color to make the light
+ public void SetSolidLight(BusylightColor color)
+ {
+ this.busylight.Light(color);
+ }
+
+ ///
+ /// Set the light to flash a given color
+ ///
+ /// The color to flash on the light
+ public void SetFlash(BusylightColor color)
+ {
+ //Flash the light with the given color at 500 ms intervals (1Hz)
+ this.busylight.Blink(color, 5, 5);
+ }
+
+ #endregion
+ }
+}
diff --git a/PanoptoRRLightService/Properties/AssemblyInfo.cs b/PanoptoRRLightService/Properties/AssemblyInfo.cs
index ee41a94..aad6eb9 100644
--- a/PanoptoRRLightService/Properties/AssemblyInfo.cs
+++ b/PanoptoRRLightService/Properties/AssemblyInfo.cs
@@ -31,5 +31,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.4.2.0")]
-[assembly: AssemblyFileVersion("2.4.2.0")]
+[assembly: AssemblyVersion("2.5.0")]
+[assembly: AssemblyFileVersion("2.5.0")]
diff --git a/PanoptoRRLightService/RRLightService.cs b/PanoptoRRLightService/RRLightService.cs
index fe90e6a..37f70f5 100644
--- a/PanoptoRRLightService/RRLightService.cs
+++ b/PanoptoRRLightService/RRLightService.cs
@@ -22,6 +22,7 @@ public partial class RRLightService : ServiceBase
private DelcomLight delcomLight = null;
private SwivlChicoLight chicoLight = null;
private SerialComm serialComm = null;
+ private KuandoLight kuandoLight = null;
///
/// Constrocutor.
@@ -54,7 +55,6 @@ protected override void OnStart(string[] args)
this.stateMachine = new StateMachine();
this.remoteRecorderSync = new RemoteRecorderSync((IStateMachine)this.stateMachine);
-
if (string.Equals(Properties.Settings.Default.DeviceType, "Delcom", StringComparison.OrdinalIgnoreCase))
{
// Set up of Delcom light (with button) device.
@@ -107,6 +107,20 @@ protected override void OnStart(string[] args)
throw new ApplicationException("Failed to start up Serial component. Terminate.");
}
}
+ else if (string.Equals(Properties.Settings.Default.DeviceType, "Kuando", StringComparison.OrdinalIgnoreCase))
+ {
+ this.kuandoLight = new KuandoLight((IStateMachine)this.stateMachine);
+ lightControl = this.kuandoLight as ILightControl;
+
+ if (this.kuandoLight.Start())
+ {
+ Trace.TraceInformation("Kuando Busylight service started");
+ }
+ else
+ {
+ Trace.TraceError("Failed to start up Kuando component. Service continues to run without support for the device");
+ }
+ }
// TODO: add here for device specific start up when another device type is added.
else
{
@@ -115,6 +129,7 @@ protected override void OnStart(string[] args)
// Start processing of the state machine.
this.stateMachine.Start(this.remoteRecorderSync, lightControl, resultReceiver);
+ Trace.TraceInformation("Started program");
}
///
@@ -146,6 +161,12 @@ protected override void OnStop()
this.serialComm = null;
}
+ if (this.kuandoLight != null)
+ {
+ this.kuandoLight.Stop();
+ this.kuandoLight = null;
+ }
+
if (this.stateMachine != null)
{
this.stateMachine.Stop();
diff --git a/PanoptoRRLightService/RRLightService.csproj b/PanoptoRRLightService/RRLightService.csproj
index edbb1bb..7549033 100644
--- a/PanoptoRRLightService/RRLightService.csproj
+++ b/PanoptoRRLightService/RRLightService.csproj
@@ -51,6 +51,10 @@
true
+
+ False
+ Kuando\BusylightSDK.dll
+
False
\\tfs\tfsbuilds\pre_prod_x86_Official\pre_prod_x86_Official_20151216.1\RemoteRecorderAPI.dll
@@ -74,6 +78,8 @@
+
+
Component
@@ -149,6 +155,9 @@
chicntrl.dll
+
+
+
diff --git a/PanoptoRRLightServiceInstaller/CustomWelcomeDlg.wxs b/PanoptoRRLightServiceInstaller/CustomWelcomeDlg.wxs
index 6f8ae46..ca1efee 100644
--- a/PanoptoRRLightServiceInstaller/CustomWelcomeDlg.wxs
+++ b/PanoptoRRLightServiceInstaller/CustomWelcomeDlg.wxs
@@ -9,6 +9,7 @@
+