Skip to content

Commit

Permalink
Merge Payload for version 2.5.0.
Browse files Browse the repository at this point in the history
Adding the support of Kuando Busylight UC Alpha and Omega.
  • Loading branch information
hohno-panopto committed Jun 14, 2018
1 parent ee29a1e commit 9cede2a
Show file tree
Hide file tree
Showing 9 changed files with 353 additions and 5 deletions.
Binary file added PanoptoRRLightService/Kuando/BusylightSDK.dll
Binary file not shown.
231 changes: 231 additions & 0 deletions PanoptoRRLightService/Kuando/KuandoLight.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
using System;
using System.Threading;
using System.Diagnostics;
using Busylight;

namespace RRLightProgram
{
class KuandoLight : ILightControl
{
#region variables

/// <summary>
/// Interface that can post events to a state machine.
/// Does nothing because Kuando Busylight has not input parameters
/// </summary>
private IStateMachine stateMachine;

/// <summary>
/// Controls light controls
/// </summary>
private KuandoLightWrapper wrapper;

/// <summary>
/// Event indicating the background threads should stop
/// </summary>
private ManualResetEvent stopRequested = new ManualResetEvent(initialState: false);

/// <summary>
/// Internal structure to carry the light control request.
/// </summary>
struct LightControlRequest
{
public LightColor Color;
public bool Flash;
};

/// <summary>
/// Latest request of light control. Older pending request is disposed by overwrite.
/// </summary>
private LightControlRequest? outstandingRequest = null;

/// <summary>
/// Lock to access outstandingRequest variable.
/// </summary>
private object outstandingRequestLock = new object();

/// <summary>
/// Event to be fired when a request is queued.
/// </summary>
private ManualResetEvent outstandingRequestExist = new ManualResetEvent(initialState: false);

/// <summary>
/// Background thread to process light control requests.
/// </summary>
private Thread processLightControlRequestsThread;

#endregion

#region Constructor, Initialize

/// <summary>
/// Constructor
/// </summary>
/// <param name="stateMachine">The state machine</param>
public KuandoLight(IStateMachine stateMachine)
{
if (stateMachine == null)
{
throw new ArgumentException("stateMachine cannot be null.");
}
this.stateMachine = stateMachine;
}

/// <summary>
/// Start the kuando light service
/// </summary>
/// <returns>Whether the service was started successfully</returns>
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;
}

/// <summary>
/// Stop the Kuando light service
/// </summary>
public void Stop()
{
this.stopRequested.Set();
this.processLightControlRequestsThread.Join();

this.wrapper.Close();
}

#endregion


#region Light Control Logic

/// <summary>
/// Continue in a thread while the service is running and check for new LightControlRequests
/// </summary>
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);
}

}
}

/// <summary>
/// Convert a LightColor to a BusylightColor, which can be recognized by Kuando devices
/// </summary>
/// <param name="inputColor">The LightColor input</param>
/// <returns>The BusyLightColor corresponding to the input</returns>
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

/// <summary>
/// Create a new request for the Kuando light to flash a given color.
/// </summary>
/// <param name="color">The color to flash on the light</param>
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);
}
}

/// <summary>
/// Set the Kuando light to be a solid color
/// </summary>
/// <param name="color">The color to set the light to</param>
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
}
}
82 changes: 82 additions & 0 deletions PanoptoRRLightService/Kuando/KuandoLightWrapper.cs
Original file line number Diff line number Diff line change
@@ -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
/// <summary>
/// Kuando busylight object. Controls turning light on/off and color
/// </summary>
private Busylight.SDK busylight;

#endregion

#region Device Setup

/// <summary>
/// Constructor
/// </summary>
public KuandoLightWrapper()
{
this.busylight = new Busylight.SDK();
this.TurnOffAllLights();
}

/// <summary>
/// Close the wrapper and turn off lights
/// </summary>
public void Close()
{
this.TurnOffAllLights();

this.CloseDevice();
}

/// <summary>
/// Close Kuando device
/// </summary>
private void CloseDevice()
{
busylight.Terminate();
}

/// <summary>
/// Turn off the connected lights
/// </summary>
private void TurnOffAllLights()
{
busylight.Light(BusylightColor.Off);
}

#endregion

#region Light control

/// <summary>
/// Turn on the light as a solid color
/// </summary>
/// <param name="color">The color to make the light</param>
public void SetSolidLight(BusylightColor color)
{
this.busylight.Light(color);
}

/// <summary>
/// Set the light to flash a given color
/// </summary>
/// <param name="color">The color to flash on the light</param>
public void SetFlash(BusylightColor color)
{
//Flash the light with the given color at 500 ms intervals (1Hz)
this.busylight.Blink(color, 5, 5);
}

#endregion
}
}
4 changes: 2 additions & 2 deletions PanoptoRRLightService/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
23 changes: 22 additions & 1 deletion PanoptoRRLightService/RRLightService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
/// Constrocutor.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
{
Expand All @@ -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");
}

/// <summary>
Expand Down Expand Up @@ -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();
Expand Down
Loading

0 comments on commit 9cede2a

Please sign in to comment.