12-08-2008 05:24 PM
I am trying to understand how UI controls work in code modules called by TestStand steps. I can pass a reference to an Application Manager (perhaps the application manager?) to my code module using RunState.engine.GetInternalOption(InternalOption_ApplicationManager). Does the sequence editor have an application manager? Or the engine? Is this the same as the Application Manager control I put on the front panel of the code module? What about SequenceViewManagers and ExecutionViewManagers? Can I create those in my code modules to display sequences or executions? Or can I somehow get those from the sequence editor/engine, or from the Application Manager?
I know that I just asked a lot of questions, but I guess what I am looking for is some general guidelines for using the manager controls in code modules. This all came about by an attempt to display an Execution View Manager control in my code module. Feel free to ignore the following description of my various attempts to get this to work. This exercise helped me understand the managers a little bit more, but I'm still a little confused.
Suppose I want to create a custom step type for debugging to display the variables for the current sequence context on the front panel of a code module VI. (LabVIEW 8.6, TestStand 4.1.) In my code module, I call ExecutionViewMgr.ConnectVariables to connect to a VariableView control. Where do I get my ExecutionView Mangager from? I tried two methods:
1) create an ExecutionViewManager control; set the manager's current execution using ExecutionViewMgr.Execution (pass RunState.Execution from TestStand to the code module).
It seems like this should work, but when I run my sequence from the sequence editor, the ExecutionViewMgr.Execution property node returns error -17500.
When I run from a LabVIEW Operator Interface (using the LabVIEW environment, not the exe), I don't get an error. But I must connect a list control using ExecutionViewMgr.ConnectExecutionList, and select the execution from the list when the code module is running. Then I can see the variables when I select the execution in the list. However, the execution display on the OI goes blank. I can see either the variables on my code module or the execution on my OI, but not both simultaneously. It appears that an execution cannot be attached to more than one manager at once (I guess that's reasonable).
2) pass the result of RunState.engine.GetInternalOption(InternalOption_ApplicationManager) to the code module; set the manager's current execution using ApplicationMgr.GetExecutionViewMgr() (pass RunState.Execution from TestStand to the code module, then as a parameter to GetExecutionViewMgr() ).
In this case, I would expect that there is no ExecutionView Manager associated with the execution when running from the sequence editor. But the ApplicationMgr.GetExecutionViewMgr() function returns a non-Null reference. ExecutionViewMgr.ConnectVariables() causes an error dialog to be displayed (from the function itself, not from TestStand), although it doesn't actually output an error (and the VariableView control remains blank). The error is "Unable to connect Variables View control." (See attachment.)
When I run from my LabVIEW OI, it works perfectly--I see the variables on my code module's UI, and the execution appears on the OI simultaneously. I guess this makes sense since the TestStand engine is returning the Execution manager that was already created by the OI.
12-10-2008 01:39 AM
Hello,
My first question is the use case. I understand that you mentioned wanting to see the variable in the code module but why exactly? You can use the sequence editor or UI to view the variables for a particular execution.
It's possible to use UI controls in code modules but I am not sure if it's the way to go or not for your application.
Some resources that I believe will help immensly are the following:
TestStand Reference Manual (Program Files>>National Instruments>>TestStand x.x>>Documentation>>Manuals
-Specifically chapter 1 and chapter 9
NI TestStand Advanced Architecture Series
-Best Practices for NI TestStand User Interface Development
Definitely check those out and feel free to ask any questions, I highly recommend using UI Controls only in your User Interface.
12-10-2008 09:45 AM
One of the reasons I considered using UI controls in a code module is that I discovered that there is a function Engine.GetInternalOption(InternalOption_ApplicationManager) that returns the that can be used by a code module return the applicaiton manager to a code module. (Use of this function was suggested in this thread: http://forums.ni.com/ni/board/message?board.id=330&message.id=22347#M22347.) So this function presumably was implemented because there is a use case for accessing the Application Manager in a code module, right? But perhaps not for the Execution or Sequence View Managers. In any case, I haven't seen anything written anywhere about using UI controls in code modules, so I wanted to know if anyone had any opinions.
I think being able to see variables in a code module may be useful in a couple of ways:
1) it allows you to see the sequence context for the currently running step, which you can't get from the sequence edtior or UI
2) It could be helpful for examining some propertyobject while running from a UI that doesn't provide a variable view. It's kind of like a LabVIEW probe. There are other solutions, but this seemed like a pretty easy solution that doesn't require you to switch to another UI or even search through hierarchies or multiple threads or executions to find a specific property.
Prior to the advent of the manager funcitons, I created my own sequence property viewer utility step type to display the properties for the sequence context passed to it. It worked okay, but I had some problems getting some of the property names. But the UI control would do all the work for me!
Anyway, another potential use case for me is more important. This could be a really bad idea, so I would like to hear your thoughts. I want to test multiple UUTs simultaneously (parallel model), and have a single UI that allows the operator to enter the serial number and start the execution for each UUT, and also show each UUT's status (e.g., the current step or current seqeunce name). Client sequence files will be determined dynamically based on serial number, so I don't really need (or want) a separate UI to allow an operator to select a sequence file or to launch the Test UUTs entry point.
One possible implementation of this design would be to modify the parallel model's serial number dialog to include a UI control for each UUT to show (say) the current sequence. This would require an Execution View Manager for each socket. I'd probably also need to include a UIMessage handler and other code that would normally be in the UI. Is this a feasable implementation? Of course, I could put all this code in the UI instead, but then then a lot of the execution management logic would have to be there, which goes against the principle of keeping the UI a simple thin client.
12-12-2008 04:18 PM
Hello,
You raised some extremely interesting points and gave a great use case as well. I have notified our R&D department of the 1st case (execution cannot be attached to more than one manager at once) to confirm whether this is expected behavior or not.
As for the second case, it looks like this might have to do with being in-process vs. out-of-process. Try running that code module with the LabVIEW Runtime so it will be running in-process (you can do this using the "Advanced Settings" for the code module). I am curious to see if this will then give you the same behavior using the Sequence Editor as running in the UI does.
You will receive another post after we look more into your first method.
12-14-2008 12:39 PM
David,
Thanks for your response. I tried use the sequence editor to call my code module using the LV RTE instead of the LV development environment. Here is what I found, using my two methods of obtaining an ExecutionView Manager:
1) Create an ExecutionViewManager control; set the manager's current execution using ExecutionViewMgr.Execution (pass RunState.Execution from TestStand to the code module) :
As before, I get en error -17500. But after I acknowledge the TS run-time error dialog, I get two concurrent dialogs from the sequence editor (the title of the dialogs is "Sequence Editor") saying, "Object reference not set to an instance of an object." After I acknowledge those dialogs, the execution window is empty and its title is blank. I can close the exeuction window, but TestStand hangs when I try to quit. If I set the "Break" option in the TS run-time error dialog, I only get one Sequence Editor Dialog, the exeuction window is still empty with a blank title, but the buttons to continue execution are disabled. (It's behaving as if the code module is still running.) I can still close the execution window, but when I try to quit TS, I get a dialog telling me the execution is still running, allowing me to terminate or abort.
2) pass the result of RunState.engine.GetInternalOption(InternalOption_ApplicationManager) to the code module; set the manager's current execution using ApplicationMgr.GetExecutionViewMgr() (pass RunState.Execution from TestStand to the code module, then as a parameter to GetExecutionViewMgr() :
I get the same behavior as before: I get an error dialog from the ExecutionViewMgr.ConnectVariables() function itself, but the error output of the invoke node does not contain an error. The Variable View control is blank.
12-15-2008 02:03 PM
jsiegel -
The main purpose of the GetInternalOption to return a reference to the ApplicationMgr was for customers to access the control the sequence editor was using, so that some customers could call properties and methods on the control. A few customers have used its events for notification of various issues and in general this works. However, we have not tried to connect controls created in non-UI threads and connect them to the ApplicationMgr, so it is unlikely that we can support this right now. The controls will definately not work if the manager and client control are in different processes.
Also, the VariablesView control only displays information in a suspended execution, i.e. at a breakpoint. The control is blank when an execution is running, i.e in a code module. The only execution information that we currently display in a running execution is the watch view pane, but even this is only refreshed on a trace message, so while in a code module, the information does not refresh.
The only options that you have to display the context is to create your own control and access the context reference, or call Engine.DisplayBrowsePropertyObjectDialog, which displays a modal dialog.
12-15-2008 09:21 PM
Scott, thanks for that answer. If I understand you correctly, the sequence editor has its own ApplicationMgr (which can be obtained from GetInternalOption()), which is analogous to the ApplicationMgr that one would create on a UI. What happens if you run from a UI instead? Does GetInternalOption() return the ApplicationMgr from the OI? Or a different one?
Also, from what you said, it sounds like it is okay to register for events from the ApplicationMgr in a code module. Is this true? Given that the UI or the sequence editor also registers for events, do events get seen by both handlers, or does one take priority and prevent the other one from seeing the events?
But it sounds like it's not okay to either have an ExecutionViewMgr (or SequenceViewMgr) or obtain an ExecutionViewMgr (or SequenceViewMgr) from the ApplicationMgr in a code module.
With this information, I am still trying to figure out the best way to have a combined serial number entry GUI and execution display GUI for multiple test sockets. It makes more sense to me to add status information to the serial number entry dialog in the parallel model (and have no UI) than to add serial number entry code to a UI (and hide the process model serial number entry dialog).
The second method requires additional synchronization between the the UI and the process model. In order for this scheme to work correctly, the UI and the process model have to be paired--one can't work without the other. This goes against the goal of having a generic UI that can work with any process model.
I used the first method in a previous project, and it worked great. The GUI didn't have any TS UI controls or respond to any events--I just used code modules to update the display as necessary. I think this is probably the route I will go for my current project, but it would be nice to be able to take advantage of the functionality of the TS UI controls. What would you suggest?
I would expect that this would be a fairly common use case, and I'm surprised that I haven't been able to find any examples. Has anyone else done something similar?
12-16-2008 02:18 PM
TestStand only allows a single ApplicationMgr per process, creating a second one will error. So the engine will always return the one in either the UI or the Sequence Editor. Events should be seen by both handlers. You have to be careful to ensure that your extra handler does not mess up the UI's handler if yours is called first, like preacknowledging a message. As far as setting up a handler in a code module, you should be able to. However, we have not fully tested this capability, so we cannot say that we fully support this because you might run into issues. In addition, using LabVIEW might present additional issues that might not be seen in other development environments like CVI and Visual Studio. Performing some functionality that can process messages in a COM callback can cause potential hang conditions, to the less you do in a callback the better when using LabVIEW. Keep in mind that you have to ensure that you unregister your handler if the code module returns to the calling execution and you no longer want the handler to be called.
Attempting to use a new TestStand UI control in a different thread than the UI thread is not recommended because we have done almost no testing on this use case because it is not done in typical UIs.
Now, for customers that want to create a nice GUI that includes serial number prompting, but still want to be able to work with the Sequence Editor, I suggest that you implement a behavior that works with a supporting GUI, but support an alternative when a non-supporing GUI is present.
For example, you could do the following:
1. The process model can send a custom UI message synchronously to the GUI to ask for a serial number. The custom message would contain a reference to a property that contains (a) a boolean to indicate that the UI will "respond" to the message, (b) a string for specifying the serial number, and (c) a notification object from the TestStand Synchronization Server.
2. When receiving the UI message, a supporting UI will set the boolean to True, duplicate the reference passed locally, and acknowledge the UI message.
3. When the UI message returns, the exectution will determine if the UI supports the message. If yes, the exectution will (a) wait on the notifcation (b) When the user enters a serial number, the GUI will set the string property and then pulse the notification, and release the reference to the properties passed via the UI message. (c) The execution will return from the notification wait, read the serial number, and continue execution.
If no, the execution will need to use the default process model prompting or custom prompting that you devise when using the Sequence Editor.
The process model could use a UI message to determine if the GUI is supportive of this mechanism once instead of with each serial number prompt, but you get the idea.
12-17-2008 12:20 AM
Scott,
You offer some very good ideas for implementing a UI that allows for SN entry on multiple UUTs. I'm going to try this out. This scheme still has the restriction that a lot of work that really should be encapsulated in the process model has to be moved into the UI. In addition, this UI must be used with the modified process model to be useful.
In the scheme I mentioned, where the serial number entry dialog is a code module, I could use the process model with any UI--the UI would not have to be specially modified to take advantage of the process model. Therefore, I could run tests using the NI simple or full-featured UIs, as well as any other custom UIs that I want, or even a UI displaying no information at all. It's possible that the UI may duplicate information that is displayed on the SN entry display, but that's okay (especially if my SN entry display only shows some very basic information, such as the name of the currently executing step for each test socket). I could even structure my process model to have callback sequences controlling what information is displayed on the display, and client sequences could override them to customize the contents.
So I think it would be helpful to be able to display UI controls in a code module. Consider that a feature request for the next version. Do you think that's feasable, or is there some fundamental flaw in my design that makes it impractical for other reasons?
12-17-2008 10:56 AM
jsiegel -
If your only goal is to display SN information along with simple UUT information in a dialog displayed by the process model, that is basically what we have today out of the box, except we do not display current step and sequence in the dialog because the UI typically displays this. Your thoughts to obtain the current step information using exiting UI controls is the obvious way. Basically you are wanting to get the current trace information from the execution. The UIs only have a single ExecutionViewMgr control, so you cannot use this for multiple executions and we already know that you cannot have more than one ExecutionViewMgr target a single execution. The next event to consider is ApplicationMgr.UIMessageEvent. We have used this before for other types of monitoring components. You would have to filter out the messages that you want to know about and figure out which messages are associated with an execution you care about. ApplicationMgr has a lot of information about the current executions that are running, and there are messages that specify model initiates to communicate UUT state changes as well.
Basically you need to have the controlling execution for the parallel or batch model display a status GUI that receives events from the ApplicationMgr control being hosted by the UI. Your status GUI would have to manage the events returned by ApplicationMgr. Keep in mind that you should limit how much you do in the event handler to allow the ApplicationMgr to continue processing the event so that its GUI can be properly updated. If you are planning on using LabVIEW to implement you status GUI, you especially need to limit your functionality in the callback. In general the LabVIEW callback should obtain the needed information from the event and then post a deferred event to update the GUI. Review the UI chapter in the Using LabVIEW with TestStand manual for some discussion on this.
I should point out that a model can obtain current step and sequence information using a ProcessModelPreStepCallback and a ProcessModelPostStepCallback, but this adds a lot of overhead to an execution because you are executing a sequence call before and/or after each step executes. The callbacks could extract information about the current steps that is about to execute or is finishing for each threads of the execution. In general, I would not recommend this path because of the extreme overhead associated with step callback sequences.