-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding the support of Kuando Busylight UC Alpha and Omega.
- Loading branch information
1 parent
ee29a1e
commit 9cede2a
Showing
9 changed files
with
353 additions
and
5 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.