MVC In LabVIEW – Making More Modular Applications Easier

If you are reading around the internet on blogs like this you are also probably searching for the Mecca of clean, readable, maintainable code which is quick and easy.

OK, we all know that doesn’t exist but I have been working on a new MVC library that has the potential to help.

Model View Controller or MVC architectures appear to be somewhat of a staple of modern software design. The idea is that you divide your software into the three parts that interaction:
MVC Diagram (Model-View-Controller)
This helps to make your system more modular and easier to change, for example you should be able to completely change the GUI (View) without touching anything functional. There is a fairly well defined method of implementing MVC in LabVIEW using queued message handlers and user events.

I have been starting to work with Angular.js, an MVC (well MVWhatever) framework for JavaScript. In this, the view is provided by HTML & CSS pages and controllers and models are written in Javascript.  To bring it together you simply reference items in the view that exist in the scope and Angular.js does all of the binding to keep these in sync. I had to have something this simple to allow rapid and easy development of MVC applications in LabVIEW.

Luckily whilst having these thoughts, the CLD summit happened here in the UK so I proposed trying to work through this idea as part of a code challenge section of the day and managed to find a group of (hopefully) willing programmers to work through the idea with this.

The Model

So lets start with the model.

Javascript has the significant advantage of being a weakly typed language. To emulate this and to avoid the headache of having loads of VIs to manage different datatypes we defined a model which uses variants at the core to store the data.

This will have a performance impact but you can’t have it all! To make things more interesting as well I have often found it can be useful to refer into the model by name as well (this might be something we need later). Therefore these data points can get stored into a variant dictionary so that we can recall them by name.

labview variant dictionary
Adding Data Items to a Variant Dictionary

Note I have also wrapped the data items and models in objects which are in turn DVRs. objects because thats how I like to organise my code and helps to give these items a unique look, DVRs because fundamentally the model and datapoints should be common, wherever you access them in the program.

Then to access items we can update the item in the dictionary. Because we are using DVRs we actually only have to read the DVR back out and then we can update through the data class (which exposes a data write through a property node).

Updating a Data Point (Get variant attribute is in the find item VI)
Updating a Data Point
(Get variant attribute is in the get item VI)

So the model is not to difficult and to be fair there are several libraries and similar methods as essentially this is a variable engine (CVT library for example).

The View

The bit that was bugging me was the data binding. There are ways that it can be done but I really didnt want the developer to have to write any code for this, it should be as simple as naming controls in a given way without having to add another whole process to your code.

There are two basic approaches possible:

  1. Polling: Angular.js actually uses a polling mechanism checking for value changes, I have used a similar solution to bind shared variables with OPC UA tags. This involves spawning a separate process and the extra complexities with controlling this.
  2. Events: Events are highly efficient but again, we want to avoid dealing with a parallel processes. This is where event callbacks seemed to solve the problems.

Event callbacks allow you to register for an event but rather than using an event structure to define the code, we can just define a callback VI which is called every time an event fires. This happens in the background without needing a parallel process.

Despite what the help file says, these currently work without issue for front panel events as well as activeX or .net events.

This allows us to bind the data items to controls (by registering for the value change event) or bind to indicators (register for a user event which the data point fires every time it is updated).

Register Event Callback to Bind to Control
Register Event Callback to Bind to Control
VI Which is Called on Value Change
VI Which is Called on Value Change

The final step is to be able to bind to the front panel automatically, this is the simple bit. There is a VI that finds all of the labels that match a pattern {dataname} and automates the binding process.

Where can I get it?

I have packaged this code on bitbucket. Please download the VI package and give it a try.

What Next?

Firstly, let me know what you think, it makes it much more fruitful to know people are trying it and (hopefully) enjoying it.

I have a few ideas for improvements including:

  • Working out a good error handling system on the callbacks.
  • Allowing the callback VIs to be replaced with custom versions.
  • Saving and loading the model to/from file.

You can see the plans, or add bugs or features to the issues section on bitbucket.

10 Comments

  • Fabiola

    June 26, 2014

    James,

    Love how elegant and simple this approach is. This is also a good opportunity to collaborate via Bitbucket. This is the first time I try to collaborate on a public project, I was going to do a small change just to make sure I knew how to do it, but I am getting an “Access Denied” message when I do the pull request.

    Is there something special I need to do to be able to do a pull request?

    Thanks,
    Fab

    Reply
  • Fabiola

    June 26, 2014

    Nevermind, found it! I was cloning instead of forking.

    Thanks,
    Fab

    Reply
  • Norman Kirchner

    June 27, 2014

    You’ve created a global repository of all information, buyer beware. Would you make an application with global variables all over the place?
    I like the idea of finding a good solution for functionally containing different parts of an application, but I think this one will lead to more issues w/ race conditions and memory performance issues than might seem at first glance.

    Then again perhaps I’m missing something, I’m curious as to your thoughts.
    ~,~

    Reply
  • Andrea

    November 14, 2014

    It actually seems that using variant attributes to implement the dictionary is not a performance problem at all, actually more the contrary

    http://ekerry.wordpress.com/2012/09/04/using-variant-attributes-for-high-performance-lookup-tables-in-labview/

    Reply
    • Yair

      November 16, 2014

      Andrea, there are two variants here –

      The one Eli was referring to is the container, which is only used because it has the attributes mechanism and doesn’t actually have a value, so there’s no effect on the performance there. Eli was saying the performance was good because of the algorithm used to store and retrieve the attributes and that’s probably also why it’s used here.

      The one James was saying causes an issue is the one that is actually stored as an attribute – that’s the one that appears as the data in the datapoint and has to converted/copied as needed when it’s written or read.

      Reply
  • Patricio

    August 19, 2022

    The repo is not found 🙁

    Reply
    • James McNally

      October 3, 2022

      Sorry – It must have been lost when moving everything off bitbucket. I’ll have to track down if I have another copy backed up.

      Reply
  • Pen_Name

    March 6, 2023

    Did you ever find this code? I’d be interested to look at it.

    Reply
    • James McNally

      May 4, 2023

      No Sorry, I think it was on a service that I closed down.

      Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.


By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close