OK, we finally have something working. Testing has been slow since we have a lot of actual production runs going on. But today was slow for some reason.
The only way I could get this to work consistently is splitting it up into multiple scripts, one for each discrete step. This isn’t necessarily bad, since it allows us to reuse these scripts in different ways. The other thing that I realized I needed to add were wait steps, I believe this could be achieved by actually polling the resources for their status and not continuing until they reported the command as complete, but I’m not sure I know how to do that.
I’ll also add, that I am by no means a C# expert, so I’m totally open to feedback on how to make these scripts better. Flexibility would also be desired, like not always using ODTC 1.1, we have 4 ODTCs on this system, if we are running this protocol while another protocol runs we’ll need to be very careful to make sure ODTC 1.1 is available.
Open the ODTC and start heating the block/lid:
using System;
using System.Linq;
using HRB.Cellario.Scripting.API;
namespace HeatBlock.Scripting
{
public class HeatBlock : AbstractScript
{
public override void AllocateResources(IScriptingApiAllocation api)
{
api.Resources["ODTC 1.1"].Allocate();
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "allocate done"); //comment
}
public override void Execute(IScriptingApi api)
{
//open ODTC
api.Resources["ODTC 1.1"].Operations["OpenDoor"].Execute();
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "Start Wait");
System.Threading.Thread.Sleep(15000); // wait 15 seconds
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "End Wait");
//set ODTC temp
api.Resources["ODTC 1.1"].Operations["Set Temperature"].OperationParameters["Block Temperature"] = 45;
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "set block temp done"); //comment
api.Resources["ODTC 1.1"].Operations["Set Temperature"].OperationParameters["Lid Temperature"] = 45;
api.Resources["ODTC 1.1"].Operations["Set Temperature"].OperationParameters["Block Temperature Threshold"] = 5;
api.Resources["ODTC 1.1"].Operations["Set Temperature"].OperationParameters["Lid Temperature Threshold"] = 10;
api.Resources["ODTC 1.1"].Operations["Set Temperature"].OperationParameters["Blocking"] = false;
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "set lid temp done"); //comment
api.Resources["ODTC 1.1"].Operations["Set Temperature"].Execute();
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "set temp execute done"); //comment
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "Start Wait");
System.Threading.Thread.Sleep(15000); // wait 15 seconds
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "End Wait");
}
public override void ReleaseResources(IScriptingApiPostExecute api)
{
api.Resources["ODTC 1.1"].Release();
}
}
}
Moving the plate:
using System;
using System.Linq;
using HRB.Cellario.Scripting.API;
namespace Customer.Scripting
{
public class MovePlate : AbstractScript
{
/// <summary>
/// Method called ahead of execution to optionally allocate resources.
/// </summary>
/// <param name="api">Use to claim device resources that will be used in the script.</param>
public override void AllocateResources(IScriptingApiAllocation api)
{
api.Resources["Robot 1.1"].Allocate();
}
/// <summary>
/// Method called during Cellario protocol execution when a sample arrives at the scripting step.
/// </summary>
/// <remarks>Executes synchronously with the run scheduler. Device operation results not available
/// until <see cref="ReleaseResources"/> method is called.</remarks>
/// <param name="api">Access to properties and methods for interacting with the Cellario run-time scheduler,
/// samples, resources and devices operations.</param>
public override void Execute(IScriptingApi api)
{
api.Resources["Robot 1.1"].Operations["Move"].OperationParameters["Source"] = 33;
api.Resources["Robot 1.1"].Operations["Move"].OperationParameters["Destination"] = 19;
api.Resources["Robot 1.1"].Operations["Move"].OperationParameters["Labware"] = "PCR Plate";
api.Resources["Robot 1.1"].Operations["Move"].OperationParameters["Robot Speed"] = 70;
api.Resources["Robot 1.1"].Operations["Move"].OperationParameters["Block Height"] = 17.5;
api.Resources["Robot 1.1"].Operations["Move"].OperationParameters["Thickness"] = 15.1;
api.Resources["Robot 1.1"].Operations["Move"].Execute();
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "Start Wait");
System.Threading.Thread.Sleep(20000); // wait 20 seconds
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "End Wait");
}
/// <summary>
/// Method called during Cellario protocol execution when any device operations for the sample are complete,
/// allowing access to their results.
/// </summary>
/// <remarks>If a resource is allocated but not released, it will remain unavailable to the Cellario run-time scheduler.</remarks>
/// <param name="api">Access to properties and methods for interacting with the Cellario run-time scheduler,
/// samples, resources and device operations, including releasing allocated resources.</param>
public override void ReleaseResources(IScriptingApiPostExecute api)
{
api.Resources["Robot 1.1"].Release();
}
}
}
A script to “incubate” for an amount of time as entered when creating the order:
using System;
using System.Linq;
using HRB.Cellario.Scripting.API;
namespace Customer.Scripting
{
public class ScriptedWait : AbstractScript
{
/// <summary>
/// Method called ahead of execution to optionally allocate resources.
/// </summary>
/// <param name="api">Use to claim device resources that will be used in the script.</param>
public override void AllocateResources(IScriptingApiAllocation api)
{
// TODO - implement or remove if not used
// e.g. api.Resources["resource name"].Allocate();
}
/// <summary>
/// Method called during Cellario protocol execution when a sample arrives at the scripting step.
/// </summary>
/// <remarks>Executes synchronously with the run scheduler. Device operation results not available
/// until <see cref="ReleaseResources"/> method is called.</remarks>
/// <param name="api">Access to properties and methods for interacting with the Cellario run-time scheduler,
/// samples, resources and devices operations.</param>
public override void Execute(IScriptingApi api)
{
var parameters = api.CurrentRun.RunOrderParameters.Last();
int iTime;
iTime = Int32.Parse(parameters.ParameterValue) * 1000;
//var iTime = api.CurrentRun.Protocol.Parameters.
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "Start Incubate for " + iTime + " milliseconds");
System.Threading.Thread.Sleep(iTime); // wait
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "End Incubate");
}
/// <summary>
/// Method called during Cellario protocol execution when any device operations for the sample are complete,
/// allowing access to their results.
/// </summary>
/// <remarks>If a resource is allocated but not released, it will remain unavailable to the Cellario run-time scheduler.</remarks>
/// <param name="api">Access to properties and methods for interacting with the Cellario run-time scheduler,
/// samples, resources and device operations, including releasing allocated resources.</param>
public override void ReleaseResources(IScriptingApiPostExecute api)
{
// TODO implement or remove if not used
// e.g. var result = api.Resources["resource name"].Operations["operation name"].Execute();
// e.g. api.Resources["resource name"].Release();
}
}
}
Move the plate again using the same script as above, and then reset the ODTC and close the door:
using System;
using System.Linq;
using HRB.Cellario.Scripting.API;
// TODO - customize namespace and class name
namespace Customer.Scripting
{
public class ResetODTC : AbstractScript
{
/// <summary>
/// Method called ahead of execution to optionally allocate resources.
/// </summary>
/// <param name="api">Use to claim device resources that will be used in the script.</param>
public override void AllocateResources(IScriptingApiAllocation api)
{
// TODO - implement or remove if not used
api.Resources["ODTC 1.1"].Allocate();
}
/// <summary>
/// Method called during Cellario protocol execution when a sample arrives at the scripting step.
/// </summary>
/// <remarks>Executes synchronously with the run scheduler. Device operation results not available
/// until <see cref="ReleaseResources"/> method is called.</remarks>
/// <param name="api">Access to properties and methods for interacting with the Cellario run-time scheduler,
/// samples, resources and devices operations.</param>
public override void Execute(IScriptingApi api)
{
api.Resources["ODTC 1.1"].Operations["Reset"].Execute();
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "Start Wait");
System.Threading.Thread.Sleep(10000); // wait 10 seconds
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "End Wait");
api.Resources["ODTC 1.1"].Operations["CloseDoor"].Execute();
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "Start Wait");
System.Threading.Thread.Sleep(10000); // wait 10 seconds
api.Messaging.WriteDiagnostic(ScriptLogLevel.Normal, "End Wait");
}
/// <summary>
/// Method called during Cellario protocol execution when any device operations for the sample are complete,
/// allowing access to their results.
/// </summary>
/// <remarks>If a resource is allocated but not released, it will remain unavailable to the Cellario run-time scheduler.</remarks>
/// <param name="api">Access to properties and methods for interacting with the Cellario run-time scheduler,
/// samples, resources and device operations, including releasing allocated resources.</param>
public override void ReleaseResources(IScriptingApiPostExecute api)
{
// TODO implement or remove if not used
// e.g. var result = api.Resources["resource name"].Operations["operation name"].Execute();
api.Resources["ODTC 1.1"].Release();
}
}
}