Community Nugget Series: Application Development: Installment 1 can be found Here
In Installment 1 of this nugget series I laid out a Model and and Architecture that I will use to develop an Automated Test System application. Today I will discuss some key considerations for the GUI or Corporate Communications Unit of the Test System Model:
All GUIs have some design targets. As a rule they should:
It would take months to fully delve into best practices and ideas for GUI construction. I recommend visiting the UI Interest Group Community pages for some excellent discussion on the HOWs of GUIs and many good ideas on the subject. Today, I want to focus on the ATS challenges to provide a responsive front panel while remaining informed by the rest of the system.
The ATS application Corporate Communications Unit is going to receive requests to take actions from a user and from other business units at times that cannot be pre-determined. From the Model Diagram we know it is not going to do much about theses requests other than to hand off most of the time consuming tasks to the Executive unit and wait for the next request. In our "Business model" this make sense. A customer walks in the door and asks the receptionist to "Test a Widget" for them. Bad practice would be for the Receptionist to go to the production floor, Test the widget, File a report, update the database and wait for the customer to review the data (if they are still there- I'd walk out!) A better practice would be for the Receptionist to let management know about the customer's request, show the customer test progress and see if there is anything else the customer needs while they are there.
A quick look through the LabVIEW VI templates shows a "Producer/Consumer Design Pattern (Events)" template that most closely matches our model of the data exchange betweenCorporate Communications and the Executive department
Time to look at the ATS implementation:
For development purpose I have added some decorations to set off FP boundaries and help ogranize BD Layout. The Top is a banner section that provides application information: (A coprorate Logo is hidden in the Pict Ring showing my CLD logo) and, not all functionality is shown or even available yet (We'll add some in a bit!) But the VI RUNS!
The BD looks like this in Rev A.
As you can see the BD does some initialization, Enters an event loop that enqueues notifications to the Executive and performs some clean-up after the user chooses to exit. Additionally, a second loop is spawned to synchronize the display of the Breakpoint array and the Table so when the Table scrolls up or down the Breakpoint array moves as well. (Note: This COULD be done in the event loop With an index value change test but scrollbars generate lots of index value changes, the user won't notice the 150mSec delay on the breakpoints following the data)
Most of the GUIs functions a encapsulated in sub-vi's that perform generic actions. Most developers have a library of "re-use" components that can be dropped as needed on a block diagram. Some "Come in handy" and some are "indispensable."
Let's take a look a three of these I use
To Be Continued.....
Available Here : Just a common Wait with error handeling utility. But it points out that a LOT of example code exists on the NI website. Don't overlook the wheels that have already been invented! I use this vi FREQUENTLY. I know how it operates and I don't have to worry about coding any bugs re-writing the functionallity of the vi.
Next: The absolute first function I call on the BD of large projects. Close Modals FPs.vi. This has absolutely no function in the application! It fall into the catagory of utilities that aid development. Most larger applications contain some modal dialog vis and and, as I develope I find that I might have upwards of 50 LabVIEW windows open at any one time. If one of them is a dialog hitting RUN on any main.vi puts the modal FP on top of everything else in the app instance. It's happened often enough that I wrote this to prevent me from needing to Crash LabVIEW and loose changes I have reciently made.
Third: a nice Action Engine that was developed from example code found here
A re-use library is a must have- even if you need to download it from multiple sources.
Going back to our Corporate Communications GUI. From Our structure and model we can see that we need to move a lot of data around. Some if the data has impecations throughout the application, some is needed only in the GUI, and some is needed only in specific sections of the BD. Often getting this data from the GUI to where it is used or From where it is generated to the GUI shows up as Forum threads "How can I access my Control in a sub-vi?) This vi had many different examples of moving data around so it seems like a good place to talk about data scoping and how LabVIEW can transfer it.
If anyone hasn't read Ben's nugget on Action Engines Come back after you go though it here We will start with the FVG and AE and take a step beyond (But not all the waty to Nirvana.)
As a quick Review:
A FGV is a data storage unit: Breakpoint FGV.vi is an example of a FGV it sets or gets values on 1 USR taking no other action on the data.
An AE is a data storage unit that can act on the data its a FGV with States. App Kind AE.vi is an Action Engine
There is a subset of AE's, A special kind of AE, that operates specifically a referance to a resource maintained on its shift register. I call this type of AE a "Module" In encapsulates all the functions of the resource and provides an abstaction layer to the next level of code (that is, the callers only need to say what to do the module handles the how to do it)
The simplest way to pass data is on a wire- Source to Sink. This gives you access to a Value and values are useful- to computers! To pass them to a user we interperate values for human consumption as a property of a control or indicator object. We pass these values to controls and indicators through Termials, Local variables or Property nodes. Terminals and local variables can only point to objects on the front panel of the vi they are found on. They have the same "Scope" as the VI they belong to.
A VI Server referance to an object changes that! Put a VI server referance on a USR inside a module and you've got a pretty powerful tool.
Data Table.vi is one such tool Table Meth.ctl Lists the actions that I can take on the GUI data table and because it carries the referance to the actual GUI object with it, I can take any of these actions from any point in my project and the Data table will show the result of the action. In effect I have brought Data Table into the scope of every vi I drop Data Table.vi onto.
Using this VI I can report Operations Results directly to the user without duplicating the Data, The executive can populate "Steps" from a configuration file ADN the Accountant can generate reports from the exact same data. I also avoid race conditions since only one action can be taken at a time and if I loose any data or things "Look wonkey" I have 1 vi to look for to debug my large app.
I'm still (re)reading and digesting this.
I have to admit the nugget did not format quite as intended. I had intended to launch on Monday 4-15 and was hoping to autosave as a first cut rough draft when I hit Post after collecting attachments (to zip from home this weekend). I wound up with 2 minutes to clear "notes to self" and add the TBC on post 1. A generic example project with a "Module" should hit this thread over the weekend to demonstrate the scope change you can obtain with the special case Action Engine I refer to as a Module.
I like this, so here is my share:
I've got a reuse package that deals with different access levels/user accounts. Depending on the user, Buttons are made visible/invisible.
Sorry, I can't share the code. There are some hardcoded master passwords inside.
Good reuse practices are a key to fast and reliable software developement. In addition to plenty of code found in this forum and the NI community pages, some great stuff can be found here:
As a side note: I always like an error case around the event structure. This way I go immediatly to the shut-down code and the error handler.
Thanks for sharing! Your code is quite similar to the Example I'm going to post here.
Modular and re-usable code has tremendous advantages for both development and debugging! Keeping on fwith Felix's train of thought I'll present the following code excerpt from the ATS Project. In the Zip File you should find "User Data.vi" Looking at the VI Hierarchy
We see that this short snip of the ATS project contains 3 example modules that operate on different front panel objects.
Status.vi Drivers both the Test Status and Operator instructions. One place it is called in the project is from "Show Hide Controls.vi" Since we want to hide certain controls when a test is executing. Finally, User Data.vi maintains Log-in names, passwords and permits.
To remind us all the Main vi FP now looks like this:
Again I have some decorations for Layout assistance that will be removed later.
User data.vi Also needs a Config file to maintain user information. For demonstration the file path is a block diagram constant you may need to change to evaluate the code.
By using the VI server references to the GUI FP objects I have a scalable solution to expose the test status throughout the ATS project. Decisions on "What to show the user" can be made at the appropriate level by the best "Business unit" to make the code very readable. Maintainability is improved as well! Suppose requirements changed to require password encryption. We have 1 piece of code to modify.
This is the Nugget I have Ben waiting for.
I will download and investigate closer this week-end but I think I see a GUI Controller.
Ben is correct (in a fashion) the concept of a GUI controller is fairly popular and simple to implement. Grab a cluster of references to every FP object wrap it in a sub-vi with a case for each action you want to take. (create a wrapper VI for each case and go to nirvana.)
If I remember correctly Ben explained HOW to implement this structure in this post .
I've used a slightly different approach by breaking out GUI elements by "Function." I took this approach for several reasons, KEY considerations were :
The last Question really has more to do with who you work with than personal style. Each of these Modules could be a class, an X-control, or a AE holding a resource. Working with Software Engineers specializing in LabVIEW development you get a much different answer than when working with Test Engineers with a smattering of LabVIEW Skills. Maintenance and adaptation for new product is fairly easy for most engineers / techs that are casual LabVIEW programmers.
That Said: Here is the GUI-fully functional
Log-in = ""
Jeff Bohrer = "P"
Admin = "Admin"
Jr. Tech = "Jr"
Sr. Tech = "Sr"
Engineer = "Eng"
Super User = "Super"
For Demo purposes a test execution marks time until Abort is pressed, delays 3 seconds, and generates a "Passed" execution.
I was going to take a closer look but being at home with 2009, I can't open the most recent. Could someone post a 2009 version of the app zipped up?