OtfOtxMapping

From emotive
Jump to navigation Jump to search


Introduction

One of the most important benefit of OTX is the strict separation of test logic and runtime implementation. The so called “OTX Mapping” is a platform independent access to arbitrary external systems. It can be edited inside the graphical mapping editor. The mapping consists of 4 different parts, see picture below: First, the Screen-Mapping realize an access to controls inside a graphical user interface. The Device-Mapping can execute device services inside an arbitrary device driver like a native DLL and can return their results. The context and the state mapping reads information from or writes it to the environment.

AccessToExternalSystems.png
Overview OTX Mapping
  • Allows the user an unlimited communication with any external systems from inside OTX. For example, Test bench hardware, measurement data acquisition, web services, special graphical interfaces, etc.
  • Platform neutral
  • In OTX there are 4 ways to communicate with systems outside of OTX:
  1. Screen signatures (Note: A signature describes the parameters of an interface)
  2. Device signatures
  3. Context variables
  4. Status variables
  • In OTX, there are various activities to use the screen and device signatures as well as the context and status variables, e.g. OpenScreen or ExecuteDeviceService.
  • OTX mapping binds these activities to existing external systems at runtime.
  • The OTX mapping is saved to a file

Mappings

The mapping binds OTX activities to existing external system at runtime. According to the element to be bound, this is called:

Screen Mapping

Binds a screen signature to an external screen, see AssemblyScreen.

Device Mapping

Binds a device signature to a public method of a DotNet Assembly or a Web Service.

Context Mapping

Binds a context variable to a public read only property of a DotNet Assembly.

Status Mapping

Binds a status variable to a public write only property of a DotNet Assembly.

Implementations

There are currently the following implementations for external systems.

  1. Proxy
  2. Assembly Screen
  3. DotNet Assembly
  4. Web Service
  5. Implementation by user (event interface)

Icons Warning.png Each implementation has special system requirements and can not be executed on every target system!

  • New implementations can easily be added if needed.
  • The selected implementation is stored in the so-called OTX mapping file. By exchanging this file, the same OTX procedure can be executed on different target systems (e.g., test bench A from manufacturer 1 or test bench B from manufacturer 2).

Proxy

A proxy will be used if there is no real implementation or implementation by the user, see below. A proxy is an implementation without function.

Icons Note.png When a procedure is executed which is used a proxy, all activities with access to external systems, e.g. OpenScreen or ExecuteDeviceService, perform a NOP (no operation).
  • A proxy stores the interface in an XML file
  • A proxy can be graphically edited in the OTX Mapping Editor
  • The OTX mapping editor can generate screen and device signatures as well as context and status variables from a proxy, and vice versa.

AssemblyScreen

An AssemblyScreen implementation is a DotNet class that is marked as a screen by special attributes, see table below. The attributes show the OTX Runtime which public methods, properties or events are used to open a screen or set a parameter. The screen can be implemented with an arbitrary complexity within the class, e.g. in WPF. In some cases, it may be useful not to create a screen, but to do something else, e.g. a database access.

The AssemblyScreen implementation supports the following OTX data types:

  • All simple data types (Boolean, Integer, Float, String)
  • ByteField
  • BlackBox
  • List which contains one of the listed data type in an arbitrary depth
  • Map which contains the listed data types in an arbitrary depth
  • Structure which contains the listed data types in an arbitrary depth
  • Enumeration


C# Code Sample (Sample PTX with including Visual Studio Project, see folder ./OTX-Mapping/Apps/OtxMappingSample/)

using OtxMappingSample.Forms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;

namespace OtxMappingSample
{
    [OtxScreenSignature]
    public class Screen1
    {
        #region fields

        private string inputText;
        private bool checkedBox = false;
        private static int count = 0;
        private string buttonText;
        private Screen1Form displayWindow;
        private MyStructure myStructure = new MyStructure();
        private MainColors mainColor = MainColors.None;

        public delegate void ScreenSignatureParameterValueChangedEventHandler(string propertyName, object value);

        #endregion

        #region ctors

        public Screen1()
        {
        }

        #endregion

        #region screen methods

        [OtxScreenSignatureParameterValueChangedEvent]
        public event ScreenSignatureParameterValueChangedEventHandler ScreenSignatureParameterValueChangedEvent;

        [OtxOpenScreen]
        public Form OpenScreen()
        {
            if (displayWindow == null)
            {
                displayWindow = new Screen1Form();

                displayWindow.Closed += DiplayWindow_Closed;
                displayWindow.textBoxTest.TextChanged += new EventHandler(textBoxText_TextChanged);
                displayWindow.checkBoxTest.CheckedChanged += new EventHandler(checkBox_CheckedChanged);
                displayWindow.buttonClick.Click += new EventHandler(buttonClick_Click);
                displayWindow.buttonClose.Click += new EventHandler(buttonClose_Click);
                displayWindow.comboBoxEnum.SelectedIndexChanged += ComboBoxEnum_SelectedIndexChanged;
                displayWindow.buttonChangeStructure.Click += ButtonChangeStructure_Click;
            }

            return displayWindow;
        }

        [OtxCloseScreen]
        public void CloseScreen()
        {
            if (displayWindow != null)
            {
                displayWindow.Closed -= DiplayWindow_Closed;
                displayWindow.Close();
                displayWindow = null;
            }
        }

        [OtxHighlightScreen]
        public void HighlightScreen()
        {
            if (displayWindow != null)
            {
                displayWindow.Activate();
            }
        }

        [OtxScreenIsOpen]
        public bool ScreenIsOpen
        {
            get { return displayWindow != null; }
        }

        #endregion

        #region screen parameters

        [OtxScreenSignatureInParameter]
        [Description("The screen title")]
        public string Title
        {
            set
            {
                if (displayWindow == null)
                {
                    return;
                }

                displayWindow.labelTitle.Text = value;
            }
        }

        [OtxScreenSignatureInOutParameter]
        [Description("The input text")]
        public string Text
        {
            get
            {
                return this.inputText;
            }

            set
            {
                this.inputText = value;
                this.displayWindow.textBoxTest.Text = value;
            }
        }

        [OtxScreenSignatureOutParameter]
        [Description("The input text")]
        public bool Checked
        {
            get
            {
                return this.checkedBox;
            }
        }

        [OtxScreenSignatureOutParameter]
        [Description("The input text")]
        public string ButtonText
        {
            get
            {
                return this.buttonText;
            }
        }

        [OtxScreenSignatureInOutParameter]
        [Description("Also OTX-Structure can be mapped")]
        public MyStructure MyStructure
        {
            get
            {
                this.myStructure.IntegerElement++;
                return this.myStructure;
            }

            set
            {
                this.myStructure = value;
                displayWindow.textBoxStructure.Text = "StringElement1 = " + value.StringElement.ToString() + 
                    "\r\nIntegerElement = " + value.IntegerElement.ToString() + 
                    "\r\nByteFieldElement = " + ByteArrayToString(value.ByteFieldElement) + 
                    "\r\nListElement = " + ListToString(value.ListElement) + 
                    "\r\nMapElement = " + MapToString(value.MapElement) + 
                    "\r\nEnumElement = " + value.EnumElement.ToString();
            }
        }

        [OtxScreenSignatureInOutParameter]
        [Description("Also OTX-Enumeration can be mapped")]
        public MainColors MainColor
        {
            get
            {
                return this.mainColor;
            }

            set
            {
                this.mainColor = value;
                displayWindow.comboBoxEnum.Text = value.ToString();
            }
        }

        #endregion

        #region helper

        private string ByteArrayToString(byte[] byteArray)
        {
            return "0x" + BitConverter.ToString(byteArray).Replace("-", "");
        }

        private string ListToString(List<int> list)
        {
            return "{ " + String.Join<int>(", ", list) + " }";
        }

        private string MapToString(Dictionary<string, string> map)
        {
            return "{ " + String.Join(", ", map.Select(x => x.Key + " : " + x.Value).ToArray()) + " }";
        }

        private void buttonClose_Click(object sender, EventArgs e)
        {
            this.CloseScreen();
        }

        private void buttonClick_Click(object sender, EventArgs e)
        {
            count++;
            this.buttonText = displayWindow.buttonClick.Text + " " + count;
            if (ScreenSignatureParameterValueChangedEvent != null)
            {
                ScreenSignatureParameterValueChangedEvent("ButtonText", this.buttonText);
            }
        }

        private void checkBox_CheckedChanged(object sender, EventArgs e)
        {
            this.checkedBox = displayWindow.checkBoxTest.Checked;
            if (ScreenSignatureParameterValueChangedEvent != null)
            {
                ScreenSignatureParameterValueChangedEvent("Checked", this.checkedBox);
            }
        }

        private void textBoxText_TextChanged(object sender, EventArgs e)
        {
            this.inputText = displayWindow.textBoxTest.Text;
            if (ScreenSignatureParameterValueChangedEvent != null)
            {
                ScreenSignatureParameterValueChangedEvent("Text", this.inputText);
            }
        }

        private void ButtonChangeStructure_Click(object sender, EventArgs e)
        {
            if (ScreenSignatureParameterValueChangedEvent != null)
            {
                ScreenSignatureParameterValueChangedEvent("MyStructure", this.myStructure);
            }
        }

        private void ComboBoxEnum_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!Enum.TryParse(displayWindow.comboBoxEnum.Text, true, out this.mainColor))
            {
                this.mainColor = MainColors.None;
            }

            if (ScreenSignatureParameterValueChangedEvent != null)
            {
                ScreenSignatureParameterValueChangedEvent("MainColor", this.mainColor);
            }
        }

        private void DiplayWindow_Closed(object sender, EventArgs e)
        {
            CloseScreen();
        }

        #endregion

        #region enums

        public enum MainColors
        {
            None,
            Red,
            Green,
            Blue
        }

        #endregion

        #region classes

        [OtxStructure]
        public class MyStructure
        {
            private string stringElement = "Hello World";
            private int integerElement = 12;
            private byte[] byteFieldElement = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
            private List<int> listElement = new List<int> { 1, 2, 34 };
            private Dictionary<string, string> mapElement = new Dictionary<string, string>() { { "1", "a" }, { "2", "b" } };
            private MainColors enumElement = MainColors.Green;

            [OtxStructureElement]
            public string StringElement
            {
                get { return stringElement; }
                set { stringElement = value; }
            }

            [OtxStructureElement]
            public int IntegerElement
            {
                get { return integerElement; }
                set { integerElement = value; }
            }

            [OtxStructureElement]
            public byte[] ByteFieldElement
            {
                get { return byteFieldElement; }
                set { byteFieldElement = value; }
            }

            [OtxStructureElement]
            public List<int> ListElement
            {
                get { return listElement; }
                set { listElement = value; }
            }

            [OtxStructureElement]
            public Dictionary<string, string> MapElement
            {
                get { return mapElement; }
                set { mapElement = value; }
            }

            [OtxStructureElement]
            public MainColors EnumElement
            {
                get { return enumElement; }
                set { enumElement = value; }
            }
        }

        #endregion

        #region attributes

        [AttributeUsage(AttributeTargets.Method)]
        internal class OtxCloseScreen : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Method)]
        internal class OtxHighlightScreen : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Method)]
        internal class OtxOpenScreen : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Property)]
        internal class OtxScreenIsOpen : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Class)]
        internal class OtxScreenSignature : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Property)]
        internal class OtxScreenSignatureInOutParameter : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Property)]
        internal class OtxScreenSignatureInParameter : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Property)]
        internal class OtxScreenSignatureOutParameter : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Property)]
        internal class OtxScreenSignatureTermParameter : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Event)]
        internal class OtxScreenSignatureParameterValueChangedEvent : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Class)]
        internal class OtxStructure : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Property)]
        internal class OtxStructureElement : Attribute
        {
        }

        #endregion
    }
}
Icons Note.png In this case, the method indicated by the OpenScreen attribute can also return NULL.

Attribute List

The following table lists all supported attributes. The attributes are only a marker, that the mapping can find the right elements. You can create the attributes by yourself or you can use the file Attributes.cs inside the sample project above.

Attribute Description
[OtxScreenSignature] Class containing the screen. There can be several classes.
[OtxScreenSignatureTermParameter] Write property that sets the value of a ScreenSignatureTermParameter
[OtxScreenSignatureInParameter] Write property that sets the value of a ScreenSignatureInParameter
[OtxScreenSignatureOutParameter] Read property, which reads out the value of a ScreenSignatureOutParameter
[OtxScreenSignatureInOutParameter] Read and write property that reads or sets the value of a ScreenSignatureInOutParameter
[OtxScreenIsOpen] Reading property, which checks if the screen is open
[OtxOpenScreen] Method in which the screen is generated (returns a form object of this screen)
[OtxCloseScreen] Method in which closes the screen
[OtxHighlightScreen] Method in which the screen comes to the foreground
[OtxScreenSignatureParameterValueChangedEvent] Event that the OTX Runtime signals that a parameter has changed in the screen
[OtxStructure] Class describing an OTX structure
[OtxStructureElement] Read and write property within the class that describes an element of the structure
[Description] Optional description for display in the OTX Mapping Editor (from System.ComponentModel)

DotNet Assembly

A DotNet Assembly implementation is a DotNet class which public methods can be bound to a device service. A bound method can be called inside OTX via an ExecuteDeviceService activity. The called device service can be implemented with an arbitrary complexity within this class.

The DotNet Assembly implementation supports the following OTX data types:

  • All simple data types (Boolean, Integer, Float, String)
  • ByteField
  • BlackBox
  • List which contains one of the listed data type in an arbitrary depth
  • Map which contains the listed data types in an arbitrary depth
  • Structure which contains the listed data types in an arbitrary depth
  • Enumeration


C# Code Sample (Sample PTX with including Visual Studio Project, see folder ./OTX-Mapping/Apps/OtxMappingSample/)

using System.Collections.Generic;
using System;
using System.Threading;
using System.Windows.Forms;
using System.ComponentModel;

namespace OtxMappingSample
{
    public class Device1
    {
        #region fields
        public delegate void DeviceEventHandler(string DeviceServiceName, string DeviceServiceOutParameterName, object DeviceServiceOutParameterValue);
        public static event DeviceEventHandler DeviceEvent;

        #endregion

        #region ctors

        public Device1()
        {
        }

        #endregion

        #region methods

        public bool Service1(string message, string title)
        {
            return MessageBox.Show(message, title, MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk) == DialogResult.OK;
        }

        public void Service2(MyStructure myStructure)
        {
            string message = "StringElement1 = " + myStructure.StringElement.ToString() + 
                "\nIntegerElement = " + myStructure.IntegerElement.ToString() + 
                "\nByteFieldElement = " + myStructure.ByteFieldElement.ToString() + 
                "\nListElement = " + myStructure.ListElement.ToString() + 
                "\nMapElement = " + myStructure.MapElement.ToString();

            MessageBox.Show(message, "Structure Support", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
        }

        [Description("The complex data type DateTime can be mapped to OTX BlackBox data type")]
        public DateTime GetTimeNow()
        {
            return DateTime.Now;
        }

        [Description("The complex data type DateTime can be mapped to OTX BlackBox data type")]
        public void DisplayTime(DateTime time)
        {
            if (time != null)
            {
                MessageBox.Show(time.ToString());
            }
            else
            {
                MessageBox.Show("Wrong type for time. System.DateTime expected.");
            }
        }

        public void FireDeviceEvent(string message, string title)
        {
            RaiseDeviceEvent(message, title, null);
        }

        public Dictionary<int, Dictionary<long, double>> FetchValues(int numberOfMeasurements, int numberOfValues, int sleep = 0)
        {
            Dictionary<int, Dictionary<long, double>> values = new Dictionary<int, Dictionary<long, double>>();

            for (int i = 0; i < numberOfMeasurements; i++)
            {
                Dictionary<long, double> value = new Dictionary<long, double>();

                long timestamp = Convert.ToInt64((new TimeSpan(DateTime.Now.Ticks)).TotalMilliseconds);
                for (int j = 0; j < numberOfValues; j++)
                {
                    value.Add(timestamp + j, Math.Sin((timestamp + j) / 1000));
                }

                values.Add(i, value);
            }

            Thread.Sleep(sleep);

            return values;
        }

        private void RaiseDeviceEvent(string DeviceServiceName, string DeviceServiceOutParameterName, object DeviceServiceOutParameterValue)
        {
            if (DeviceEvent != null)
            {
                DeviceEvent(DeviceServiceName, DeviceServiceOutParameterName, DeviceServiceOutParameterValue);
            }
        }

        #endregion

        #region enums

        public enum MainColors
        {
            None,
            Red,
            Green,
            Blue
        }

        #endregion

        #region classes

        [OtxStructure]
        public class MyStructure
        {
            private string stringElement = "Hello World";
            private int integerElement = 12;
            private byte[] byteFieldElement = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
            private List<int> listElement = new List<int> { 1, 2, 34 };
            private Dictionary<string, string> mapElement = new Dictionary<string, string>() { { "1", "a" }, { "2", "b" } };
            private MainColors enumElement = MainColors.Green;

            [OtxStructureElement]
            public string StringElement
            {
                get { return stringElement; }
                set { stringElement = value; }
            }

            [OtxStructureElement]
            public int IntegerElement
            {
                get { return integerElement; }
                set { integerElement = value; }
            }

            [OtxStructureElement]
            public byte[] ByteFieldElement
            {
                get { return byteFieldElement; }
                set { byteFieldElement = value; }
            }

            [OtxStructureElement]
            public List<int> ListElement
            {
                get { return listElement; }
                set { listElement = value; }
            }

            [OtxStructureElement]
            public Dictionary<string, string> MapElement
            {
                get { return mapElement; }
                set { mapElement = value; }
            }

            [OtxStructureElement]
            public MainColors EnumElement
            {
                get { return enumElement; }
                set { enumElement = value; }
            }
        }

        #endregion

        #region attributes

        [AttributeUsage(AttributeTargets.Method)]
        internal class OtxCloseScreen : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Method)]
        internal class OtxHighlightScreen : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Method)]
        internal class OtxOpenScreen : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Property)]
        internal class OtxScreenIsOpen : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Class)]
        internal class OtxScreenSignature : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Property)]
        internal class OtxScreenSignatureInOutParameter : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Property)]
        internal class OtxScreenSignatureInParameter : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Property)]
        internal class OtxScreenSignatureOutParameter : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Property)]
        internal class OtxScreenSignatureTermParameter : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Event)]
        internal class OtxScreenSignatureParameterValueChangedEvent : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Class)]
        internal class OtxStructure : Attribute
        {
        }

        [AttributeUsage(AttributeTargets.Property)]
        internal class OtxStructureElement : Attribute
        {
        }

        #endregion
    }
}

Web Service

The web service implementation allows the author to call a web service from inside OTX. An example Web service for Euro conversion is http://webservices.gama-system.com/exchangerates.asmx. The services found in the web service are bound to a device service, which can be called via the ExecuteDeviceService activity.

The web service implementation supports the following OTX data types:

  • All simple data types (Boolean, Integer, Float, String)
  • ByteField
  • BlackBox
  • List which contains one of the listed data type in an arbitrary depth
  • Map which contains the listed data types in an arbitrary depth
  • Structure which contains the listed data types in an arbitrary depth
  • Enumeration
px
OTX Mapping Editor for Web Service

User-specific (Event Interface)

The user can also implement his own implementation via the event interface of the OTX Runtime API. Detailed information can be found in the OTX Runtime user documentation (DotNet/Java). If the activity is called within an OTX procedure, the OTX Runtime API fires the corresponding event. In the event processing function, the user can then implement his own implementation.

The event interface supports the following OTX data types:

  • All simple data types (Boolean, Integer, Float, String)
  • ByteField
  • BlackBox
  • List which contains one of the listed data type in an arbitrary depth
  • Map which contains the listed data types in an arbitrary depth
  • Structure which contains the listed data types in an arbitrary depth
  • Enumeration

Mapping Editor

Inside the OTX mapping editor all mapping links can be created and edited graphically as follows:

1. Add the external application to the mapping

Icons Note.png An external application can be stored in a central directory or within the project. This is a global OTF setting.
Icons Note.png All dependencies to an external application do not need to be added. But they must be exists in the same directory as the external application!

2. Create the mappings separately for screen, device, context and status mapping

Icons Note.png The left part lists valid elements found in the external application
Icons Note.png The right part lists the corresponding OTX elements.

3. Select two matching elements on the left and the right list.

Icons Note.png Which elements matches is described above the list.

4. Clicked at the arrow between the two lists.

Icons Note.png If a parent element is selected in the right part, a new OTX element can also be generated by clicking at the arrow.

5. Optionally specify the environment preset values to simulate a certain environment.

Icons Note.png For all not already mapped Signature InOut- or Out-parameters as well as context variables a fixed value can be specified. These are values ​​that are transported from the environment into the OTX procedure.
px
OTX Mapping Editor