OTX-Runtime API Developer Reference for DotNet |
The OTX-Runtime API provides client applications with easy, fast and reliable access to OTX for runtime execution. The main task is loading of OTX projects, browsing the structure and executing of procedures.
OTX-Runtime API supports programmers to run an OTX project (PTX) or single OTX files in its own application. For the development of OTX projects please use the Open Test Framework. The API has the following features:
Browsing content to get Packages, Documents, Procedures and Parameters
Validation and returning a list of errors (Checker), see Validate
Direct excecution of the startup procedure
Executing an arbitrary Procedure and return Out- or InOut-Parameter values right after execution or during execution via event (ParameterValueChanged)
The runtime behavior of OTX extensions Logging, HMI and Measure can be switched off so that the user can use its own implementation via an event based interface, see How to use own implementations.
Handling of Context Variables
Support of Variables- and Communication-Trace
Adjustment of Project settings for various OTX Extensions like DiagCom, HMI, I18n, Logging and Quantities
Synchronous and asynchronous behaviour of Procedure execution
Thread safe execution
Multi-Instance and Multi-Threading capable (Requirement: All underlying systems, e.g. MVCI-Server, have to support this)
Long time running stable
High runtime performance
Sample program to demonstrate the complete functionality of the OTX-Runtime API, see Sample Program.
At first, you have to install the OTX-Runtime API, see Installation and Configuration. The OTX-Runtime API is included in the MSI installer of the OTF and the OTX-Runtime API.
To use OTX-Runtime API, add OpenTestSystem.Otx.Runtime.Api.dll as a reference in your project. See How to add into Visual Studio project
The RuntimeManager is the entry point of the OTX-Runtime API.
You can download some full code examples for MS Visual Studio including the source code of the complete Sample Program. To run the samples, you have to change the wrong reference of OpenTestSystem.Otx.Runtime.Api.dll to the installation location of the OTX-Runtime API.
using System; using OpenTestSystem.Otx.Runtime.Api; using OpenTestSystem.Otx.Runtime.Api.Otx; using OpenTestSystem.Otx.Runtime.Api.Otx.Parameter; static class Program { static void Main() { RuntimeManager runtimeManager = new RuntimeManager(); runtimeManager.Load("./ptx/OtxRuntimeApiHelloWorld.ptx"); IProcedure procedure = runtimeManager.GetMainProcedure(); if (procedure.Parameters[0] is InParameter) { (procedure.Parameters[0] as InParameter).Value = "Hello World"; } else if (procedure.Parameters[0] is InOutParameter) { (procedure.Parameters[0] as InOutParameter).Value = "Hello World"; } procedure.Execute(); } }
using System; using System.Windows.Forms; using OpenTestSystem.Otx.Runtime.Api; using OpenTestSystem.Otx.Runtime.Api.Otx; using OpenTestSystem.Otx.Runtime.Api.Otx.Parameter; namespace OtxRuntimeApiSample { public partial class Form1 : Form { RuntimeManager runtimeManager = null; public Form1() { InitializeComponent(); } private void buttonLoad_Click(object sender, EventArgs e) { this.UseWaitCursor = true; this.runtimeManager = new RuntimeManager(); this.runtimeManager.Load("./ptx/OtxRuntimeApiHelloWorld.ptx"); this.runtimeManager.ParameterValueChanged += new OpenTestSystem.Otx.Runtime.Api.Event.ParameterValueChangedHandler(runtimeManager_ParameterValueChanged); this.runtimeManager.ProcedureFinished += new OpenTestSystem.Otx.Runtime.Api.Event.ProcedureFinishedHandler(runtimeManager_ProcedureFinished); this.runtimeManager.VariableTraceItemAdded += new OpenTestSystem.Otx.Runtime.Api.Event.VariableTraceItemAddedHandler(runtimeManager_VariableTraceItemAdded); this.runtimeManager.ExecutionStopped += new OpenTestSystem.Otx.Runtime.Api.Event.ExecutionStoppedHandler(runtimeManager_ExecutionStopped); this.runtimeManager.RuntimeExceptionOccured += new OpenTestSystem.Otx.Runtime.Api.Event.RuntimeExceptionOccuredHandler(runtimeManager_RuntimeExceptionOccured); this.UseWaitCursor = false; } private void RuntimeManager_RuntimeExceptionOccured(IProcedure procedure, Exception exception) { throw new NotImplementedException(); } private void runtimeManager_ParameterValueChanged(IParameter parameter, IProcedure procedure) { if (parameter != null) { object value = GetParameter(parameter); AddEventToTextBox("ParameterValueChanged: Paramter: " + parameter.Name + ", Value: " + value != null ? value.ToString() : string.Empty); } } private void runtimeManager_ProcedureFinished(IProcedure procedure) { if (procedure != null) { AddEventToTextBox("ProcedureFinished: Procedure: " + procedure.Name); } } private void runtimeManager_VariableTraceItemAdded(OpenTestSystem.Otx.Runtime.Api.Types.IVariableTraceItem traceItem) { if (traceItem != null) { AddEventToTextBox("VariableTraceItemAdded: Variable: " + traceItem.Variable + ", Value: " + traceItem.Value); } } private void runtimeManager_ExecutionStopped() { AddEventToTextBox("ExecutionStopped"); } void runtimeManager_RuntimeExceptionOccured(IProcedure procedure, Exception exception) { if (procedure != null) { AddEventToTextBox("RuntimeExceptionOccured: Procedure: " + procedure.Name + ", Exception: " + exception.Message); } } public delegate void AddEventToTextBoxDelegate(string text); public AddEventToTextBoxDelegate addEventToTextBoxDelegate; private void AddEventToTextBox(string text) { if (this.textBox1.InvokeRequired) { addEventToTextBoxDelegate = new AddEventToTextBoxDelegate(AddEventToTextBox); this.Invoke(addEventToTextBoxDelegate, new object[] { text }); } else { this.textBox1.Text += text + "\r\n"; } } private void button1_Click(object sender, EventArgs e) { IProcedure procedure = this.runtimeManager.GetMainProcedure(); if (procedure != null) { SetParameter(procedure.Parameters[0], "Hello World"); procedure.Execute(); } } private void button2_Click(object sender, EventArgs e) { IProcedure procedure = this.runtimeManager.Packages[0].Documents[0].Procedures[1]; if (procedure != null) { Int64 n = 0; SetParameter(procedure.Parameters[0], n); procedure.Execute(true); } } private object GetParameter(IParameter parameter) { object value = null; if (parameter is IInOutParameter) { value = (parameter as IInOutParameter).Value; } else if (parameter is IInParameter) { value = (parameter as IInParameter).Value; } else if (parameter is IOutParameter) { value = (parameter as IOutParameter).Value; } return value; } private void SetParameter(IParameter parameter, object value) { if (parameter is IInOutParameter) { (parameter as IInOutParameter).Value = value; } else if (parameter is IInParameter) { (parameter as IInParameter).Value = value; } } } }
using System; using System.IO; using System.Windows.Forms; using OpenTestSystem.Otx.Runtime.Api; using OpenTestSystem.Otx.Runtime.Api.Otx; namespace RunPtx { internal class Program { // Execute an arbitrary PTX with this little sample console application // Syntax: RunPtx.exe PtxFilename // Example: RunPtx.exe "..\..\Resources\HelloWorldSimple.ptx" private static void Main(string[] args) { try { if (args.Length != 1) { PrintError("Syntax: RunPtx.exe PtxFileName"); } LoadAndRun(args[0]); } catch (Exception exception) { PrintError(exception.Message); } } private static void LoadAndRun(string filename) { WriteLine("********************************************************"); WriteLine("* RunPtx sample for simple execution of PTX documents. *"); WriteLine("********************************************************"); if (string.IsNullOrEmpty(filename)) { throw (new Exception("Syntax: RunPtx.exe PtxFileName")); } filename = Path.GetFullPath(filename); if (!File.Exists(filename)) { throw (new Exception("Wrong filename: " + filename)); } Write("Create OTX-Runtime instance..."); var runtimeManager = new RuntimeManager(); WriteLine(" created."); Write(string.Format("Load PTX \"{0}\"...", filename)); runtimeManager.RuntimeExceptionOccured += runtimeManager_RuntimeExceptionOccured; runtimeManager.Load(filename); WriteLine(" successfully loaded."); Write("Starting procedure..."); var procedure = runtimeManager.GetMainProcedure(); if (procedure != null) { procedure.Execute(); WriteLine(" execution finished successfully."); } else { PrintError("No main procedure found!"); } WriteLine("****************************************************************"); WriteLine("* Finished *"); WriteLine("****************************************************************"); } private static void runtimeManager_RuntimeExceptionOccured(IProcedure procedure, Exception exception) { PrintError(exception.Message); } private static void PrintError(string error) { WriteLine(error); WriteLine("****************************************************************"); WriteLine("* Exception *"); WriteLine("****************************************************************"); MessageBox.Show(error, "RunPtx Exception"); } private static void WriteLine(string output) { Console.WriteLine(output); } private static void Write(string output) { Console.Write(output); } } }
<otx xmlns="http://iso.org/OTX/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:hmi="http://iso.org/OTX/1.0.0/HMI" id="id_0a4aa7adb9484acd80fd9b8cc0889d1c" name="NewDocument1" package="NewDefaultPackage1" version="1.0.0.0" timestamp="2014-09-08T17:41:38.7630549+07:00"> <procedures> <procedure id="id_9fd318a128cd4945aa7ed8d5cd57c0b8" name="main" visibility="PUBLIC"> <realisation> <parameters> <inParam id="id_a8160a4eec9f4fa2b8d84dfd21477e08" name="Message"> <realisation> <dataType xsi:type="String"/> </realisation> </inParam> </parameters> <flow> <action id="id_6ff9b94186d64730b442cdb5f77b63f0" name="ConfirmDialog1"> <realisation xsi:type="hmi:ConfirmDialog"> <hmi:title xsi:type="StringLiteral"/> <hmi:message xsi:type="StringValue" valueOf="Message"/> <hmi:messageType xsi:type="hmi:MessageTypeLiteral" value="INFO"/> </realisation> </action> </flow> </realisation> </procedure> <procedure id="id_973b034439b14963ad18768501f71915" name="ProcedureWithInOutValue" visibility="PUBLIC"> <realisation> <declarations> <variable id="id_f28608c2ea1a4d8fb4804f55fdcd515e" name="Counter1"> <realisation> <dataType xsi:type="Integer"/> </realisation> </variable> </declarations> <parameters> <inoutParam id="id_45566163d11747678f259ebe92022b90" name="InOutParameterDeclaration1"> <realisation> <dataType xsi:type="Integer"/> </realisation> </inoutParam> </parameters> <flow> <loop id="id_8dfc001cc929459396b42916811794c7" name="ForLoop1"> <realisation> <configuration id="id_e10281431ca14258bb4b482b6b22e2b9"> <realisation xsi:type="ForLoop"> <counter name="Counter1"/> <start xsi:type="IntegerLiteral" value="0"/> <end xsi:type="IntegerLiteral" value="9"/> </realisation> </configuration> <flow> <action id="id_5f6dea28d35b4d7998f8a536696fd0f6" name="Assignment2"> <realisation xsi:type="Assignment"> <result xsi:type="IntegerVariable" name="InOutParameterDeclaration1"/> <term xsi:type="IntegerValue" valueOf="Counter1"/> </realisation> </action> <action id="id_c4bd219e5fc846dd8efcd6c7564453f1" name="ConfirmDialog1"> <realisation xsi:type="hmi:ConfirmDialog"> <hmi:title xsi:type="StringLiteral"/> <hmi:message xsi:type="ToString"> <term xsi:type="IntegerValue" valueOf="InOutParameterDeclaration1"/> </hmi:message> <hmi:messageType xsi:type="hmi:MessageTypeLiteral" value="INFO"/> </realisation> </action> </flow> </realisation> </loop> </flow> </realisation> </procedure> </procedures> </otx>