In this section there are some useful code snippets that you can use to create Custom Transforms.
Use code similar to this to define Enumerations for a port in a Custom Transform: EnumerationSet enumSet = new EnumerationSet("MyEnumSet"); enumSet.Enums.Add(new Enumeration("Enum1", 1)); enumSet.Enums.Add(new Enumeration("Enum2", 2)); enumSet.Enums.Add(new Enumeration("Enum3", 3));
DiscreteInfo discreteInfo = new DiscreteInfo("Test", SignalDataFlow.Input, 0, 10, 0, enumSet); IPort port = new InPort(this, discreteInfo); this.AddPort(port);
|
Use code similar to this to add a new property to your custom transform: double myHoldTime = 0.5; //Seconds – DEFAULT VALUE public double YourNewProperty { get { return this.myHoldTime; } set { this.myHoldTime = value; } } The property and its value are displayed in the Properties box in MxTransIt. |
Use code similar to the following to add and serialize properties. Data is stored in the mxform (XML) file. private const string TickPeriodXmlAttributeName = "TickPeriod"; private const string TimeConstantXmlAttributeName = "TimeConstant"; public override void FromXml(ITransformSpider spider, Xml.Xml3.Transform xmlTransform, IntegrityFailures failures) { base.FromXml(spider, xmlTransform, failures); if (xmlTransform.AnyAttr != null) { foreach (System.Xml.XmlAttribute attr in xmlTransform.AnyAttr) { switch (attr.LocalName) { case FirstOrderFilter.TickPeriodXmlAttributeName: this.myScheduler.Interval = double.Parse(attribute.Value); break; case FirstOrderFilter.TimeConstantXmlAttributeName: this.myTimeConstant = double.Parse(attribute.Value); break; default: break; } } } } public override Xml.Xml3.Transform ToXml() { ToXmlContext context = new ToXmlContext(System.Environment.CurrentDirectory); Xml.Xml3.Transform xmlTransform = base.ToXml(); List<System.Xml.XmlAttribute> anyAttributes = new List<System.Xml.XmlAttribute>(); if (xmlTransform.AnyAttr != null) { anyAttributes.AddRange(xmlTransform.AnyAttr); } if (this.myScheduler.Interval.Time_sec != 0) { anyAttributes.Add(context.CreateXmlAttribute(FirstOrderFilter.TickPeriodXmlAttributeName, this.myScheduler.Interval.Time_sec)); } if (this.myTimeConstant != 0) { anyAttributes.Add(context.CreateXmlAttribute(FirstOrderFilter.TimeConstantXmlAttributeName, this.myTimeConstant)); } xmlTransform.AnyAttr = anyAttributes.ToArray(); return xmlTransform; }
|
Verbs allow actions to be performed on a transform in MxTransIt. Verbs appear as links at the bottom of the properties window. This sample code for creating a Verb is from the template for custom transforms. It enables the user to set a path to the custom transform's .sln file, defines the Verb "Launch Solution," and defines an event handler for the Verb. //Allows the user to set the path to this transform's .sln file. private string mySolutionPath = @"C:\Documents and Settings\MxV Projects\CustomTransform\Transforms\ExampleCustomTransform\ExampleCustomTransform.sln"; [Category("Customized Editors")] [EditorAttribute(typeof(SolutionPathTypeEditor), typeof(System.Drawing.Design.UITypeEditor))] public string SolutionPath { get { return this.mySolutionPath; } set { this.mySolutionPath = value; } }
//Override the Verbs property to define a verb. A verb consisits of a name, and an event handler. //The name will appear as a link in the properties window of MxTransIt, //the event handler is the code that will be called when that link is clicked.
public override System.ComponentModel.Design.DesignerVerbCollection Verbs { get { DesignerVerbCollection verbs = new DesignerVerbCollection(); verbs.Add(new DesignerVerb("Launch Solution", this.LaunchSolution)); return verbs; } }
//This is the event handler for the "Launch Solution" verb. This code is called when the //link is clicked in the properties window of MxTransIt. private void LaunchSolution(object sender, EventArgs e) { if (string.IsNullOrEmpty(this.mySolutionPath)) { System.Windows.Forms.MessageBox.Show("Please specify the solution to launch.", "MxTransIt", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning); return; }
if (!System.IO.File.Exists(this.mySolutionPath)) { System.Windows.Forms.MessageBox.Show(string.Format("The solution, {0}, does not exist.", this.mySolutionPath), "MxTransIt", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning); return; }
System.Diagnostics.Process.Start(this.mySolutionPath); }
|
The basic constructor for transitions is: public Transition(Time time, IDataType data) Example in a sample Transform: ITransition responseT = new Transition(context.TickTime, new Discrete(temp));
To transmit Persistent Transitions from a port on your Transform, use this constructor when creating the transition instance: Transition(Time time, IDataType data, bool persistDuplicates) Example: Transition trans = new Transition(time, data, true); this.OutPortList[i].Transmit(trans); |
Use code similar to the following example to create output and input ports for message data on your Custom Transform: this.AddPort(new OutPort(this, new MessageInfo("OutMessage", SignalDataFlow.Output, new MemorySize(16, MemorySizeUnit.Bytes), true, MessageDisplayFormats.Ascii)));
this.AddPort(new InPort(this, new MessageInfo("InMessage", SignalDataFlow.Input, new MemorySize(16, MemorySizeUnit.Bytes), true, MessageDisplayFormats.Ascii))); To process an array of bytes, use MessageInfo. The result can be displayed as either Hex or an ASCII string. |
Use code similar to the following example to display a message in the MxVDev Notifications window. this.Failures.Add(new IntegrityFailure(IntegrityFailureSeverities.Error, IntegrityFailureSources.Transform, this.Name, string.Format("Failure message…"))); IntegrityFailureSeverities.Error – error will stop the execution of the scenario and show error IntegrityFailureSeverities.Message – message is used just for information purposes. For example: “Connection successful” IntegrityFailureSeverities.Warning – shows a yellow triangle warning in the notification, usually means there is some issue with execution but it’s not fatal You can use string.Format() to include as much useful information as possible in your error message. For example, if time is available you can add time, port info/signal name, data value, or anything that will be useful to debug and fix the error. |
The Custom Transition Editor Sample Project shows how to display a custom dialog when creating or modifying transitions. The Custom Transform in the sample takes a 4-byte message as an input, and sends each byte out as a discrete Signal on a separate outport. All 5 ports are exported to MxVDev. There is a TestCase with all 5 signals. When you double-click to add a transition on the "In" signal, the custom transition editor dialog is displayed: Use this procedure to create a similar dialog: 1.Create a new control in Visual Studio. The one in the sample is called MyCustomTransitionEditor. 2.Have this control implement the MicroMax.MxVDev.TransitionEditors.ITransitionEditor interface defined below. public interface ITransitionEditor { string CurrentScenarioDirectory { get; set; } IDataType DataType { get; set; } bool ValidateSettings(); } The data type property is set when the form opens if you are editing an existing transition. The passed in value should be used to populate the controls on the form. When the user clicks the OK button, ValidateSettings is called to run code to make sure that the settings on the control are valid to create a data type for the transition. If valid, the DataType property is read, and the returned IDataType is turned into a transition. 3.Override the CreateTransitionEditor method on the Custom Transform: public override ITransitionEditor CreateTransitionEditor(Port port, SignalDataFlow dataFlow) This method should compare the passed-in port to the ports that have transition editors, and return the appropriate control. In the sample, only the inport has a custom editor, so if it is not the inport, then we return the base implementation:
public override ITransitionEditor CreateTransitionEditor(Port port, SignalDataFlow dataFlow) { if (port == this.InPorts[0]) { return new MyCustomTransitionEditor(); } else { return base.CreateTransitionEditor(port, dataFlow); } }
|
Tick can be called periodically or when a transition arrives at the inport. For Tick to be called periodically, the Transform must have a scheduler. If the Transform does not have a scheduler, Tick is called with context type = Normal. If it has a scheduler, then usually Tick is called twice for the same time, once with Stimulus type and once for Response. Periodic Tick RateTo prevent the Transform from executing Tick on every received transition and to make it strictly periodic, use the following code: public override void Tick(TickContext context) { switch (context.TickType) { case TickContext.TickTypes.Stimulus: this.myStimulusScheduler.ExecuteUpTo(context.TickTime); ...
Related Topics: |
SetUp and TearDown are called when the Harness is loaded or reloaded, the project opened and closed, etc. SetUp may be called multiple times in a row when the Harness is loaded, so if there is some code that should be executed only once, do a context check at the beginning. For example:
public override void SetUp(SetUpContext context) { base.SetUp(context); if (this.myLastSetupContext == context) return; this.myLastSetupContext = null; ... ... this.myLastSetupContext = context; } See Execution Strategy. |
Throwing a run-time error from Custom Transform code is typically done using a line of C# code similar to the following: this.myFailures.Add(new IntegrityFailure(IntegrityFailureSeverities.Error, IntegrityFailureSources.Transform, "Error Message Description", "Error message details… etc. etc.")); This code adds a message to the Notifications window, which includes the information provided in the Severity field, the Source field, the Description field, and the Details field. Any Integrity Failure with the severity of "Error" causes a run-time event and the execution is halted for that Scenario. |