Jump to content
Sign in to follow this  
chrisempson

Actor Framework settings dialog

Recommended Posts

Hi, I'm writing a LabVIEW application using the Actor Framework. This is the first time that I have used the framework and I need some advice regarding application architecture. My apologies if this is a basic question!


 


How is a settings dialog box best implemented? In the past in non-Actor Framework applications I have loaded the configuration from a functional global variable, displayed the settings dialog, then written the updated settings back to the functional global. I'm not sure this would work correctly (or optimally) within the context of the Actor Framework, though. 


 


My application uses the template generated by Create Project -> Actor Framework. The top-level Actor manages the user interface. Two child Actors control separate pieces of hardware. The top-level actor must read a saved configuration from an INI file when the application starts, and save the final configuration back to the INI file on exit.


 


Instinctively I think it would be best for each child actor to maintain its own settings, as a cluster in its class private data. Ideally I don't want to have to keep a separate instance of the two clusters of settings in the top-level Actor's private data in order to populate a settings dialog; this duplication seems unnecessary.


 


The only way I can think of to make this work is as follows.


 


At application start


1. Top-level Actor reads settings from INI file.


2. Send messages to both child actors with the new settings, and tell them to apply those settings to their private data.


3. Each child Actor should respond to acknowledge that the private data has been updated.


 


To update the settings using a dialog box


1. Send a message from the top-level Actor to each child Actor to ask them to send their settings to the top-level Actor.


2. Wait for both child Actors to reply.


3. Display the dialog box.


4. If the user clicked 'Ok' and not 'Cancel', send messages to both actors with the new settings, and tell them to apply those settings to their private data.


5. Each child Actor should respond to acknowledge that the private data has been updated.


 


On exit


1. Send a message from the top-level Actor to each child Actor to ask them to send their settings to the top-level Actor.


2. Wait for both child Actors to reply.


3. The top-level Actor writes the settings to the INI file.


 


This doesn't seem like a sensible approach, though. Waiting for message replies sounds like the wrong thing to do. I wouldn't know where in the block diagram to implement this scheme, either.


 


Can anyone offer me any advice? There must be a fairly standard way of doing this that I'm missing!


 


Thanks in advance,


Chris


 


---


Dr. Chris Empson


Robot Screening and Instrumentation Specialist


School of Chemistry


University of Leeds


UK


 


CLD


Share this post


Link to post
Share on other sites

Thanks so much for your detailed reply, hooovahh. Your architecture makes a lot of sense, and removes the problem of having to wait for replies to messages. Doing a 1 to N message cast is a much better scheme in a distributed, asynchronous system.

 

Your point about configuration data that is shared between Actors is a good one. I was planning on adding a hardware simulation option that all of the Actors would need to know about.

 

I take your point about this architecture adding some undesired coupling, but that isn't a significant problem to me.

 

Thanks again!

Share this post


Link to post
Share on other sites

So in my setup one actor handles all File I/O, with the only exception is a single VI that is called before all actors start which does the initial read.  Config is done in pages, which are just a collection of VIs and controls.  This makes adding new settings easy, just add a new control, then read from the global which is a variant.  This way when I add a new setting there is no type defs or controls that need updating, and no new code to write, just add the control to the page VIs, and now that setting is in the INI and global for the rest of the application to read.  There is a chance for some runtime errors because of this, but these types of errors you see once in development, then make it the correct type, and never see again.  You aren't changing the type of the data mid application.  If I have a string data type that is Project Name, I'm not going to change that from a string, so once all the places that I'm reading Project Name are set to string you won't really see any errors again.

 

In your design you mentioned each actor being responsible for their own settings, but I have a few settings that aren't specific to one actor.  Under the Advanced page of my config I have a hardware simulation mode.  If this is on each actor knows to pretend it is talking to hardware and return random, or semi-random data.  I may also have multiple pages for each actor.  I have a sequence engine, and it may have multiple sequences that could be in multiple pages, or a single page with a drop down of which sequence to edit.  My point is I can have as many settings or as few, which can be shared between actors.

 

A downside of this design comes when you want to just run a single actor without having to run the configuration actor.  I realize my design adds some coupling that is generally not desired.  So I had some extra code to detect if the configuration actor isn't running, and to use predefined defaults for that actor, if it's not.

 

I think if you move to a DB, it will supply the decoupling and still give you all the same capabilities.

 

A while ago I added a "Settings" library to the SQLite API which, I think, does exactly what you're describing - almost direct replacement. You just place the VI on the diagram and you can load and save the FP controls to the DB. It also gives you "Restore to Default" and has a "query" function so you can return as many or as few parameters as you like (see the Panel Settings Example). I was also thinking about adding the "Update" event broadcast similar to your system since for Data-aware xcontrols it would be a very nice feature to have them all update on a change and would only be a couple of minutes to add.

Edited by ShaunR

Share this post


Link to post
Share on other sites

Yeah I thought about a database, and did look into using your SQLite library, but honestly it works, it's human readable, and I haven't had any real problems so I didn't see much of a need to change it yet.  I was using the OpenG INI stuff and with very large data structures it was a bit slow so I moved to MGI at some point and haven't had any issues since.

 

I think the coupling between actors would still be there even if I went to a database.  The coupling I was referring to could be minimized with several techniques, but the actual format of the file isn't going to change this, other design decisions could.  Like if each actor was responsible for doing their own configuration control, but as I said my design didn't go this way, not that this could work.

 

Oh and my setup did have a cancel option, which just wouldn't send out the 1-to-N message that a setting was changed, and it would re-read the config file, and re-write the controls in the pages.  One other thing I forgot to mention is some times pages of the config, would rely on other pages of the config.  So say I had a page that had a Show Advanced Settings checkbox.  If this was on you wanted all the other pages to show the advanced settings if there were any.  So when I sent out this 1-to-N message to the actors telling them a config was updated, I would also have that message go to each of the pages, so that they could then re-read from the global the settings from all the other pages, so they could show or hide the advanced settings based on the last applied settings.  I used this same message to the pages if you canceled too, because a cancel may revert to some state where the UI in the page needs to be updated.  I've thought about cleaning this up and posting it, but since it isn't an NI Actor, it uses a decent amount of the reuse library which would need to be made generic or released.

Share this post


Link to post
Share on other sites

Yeah I thought about a database, and did look into using your SQLite library, but honestly it works, it's human readable, and I haven't had any real problems so I didn't see much of a need to change it yet.  I was using the OpenG INI stuff and with very large data structures it was a bit slow so I moved to MGI at some point and haven't had any issues since.

 

I think the coupling between actors would still be there even if I went to a database.  The coupling I was referring to could be minimized with several techniques, but the actual format of the file isn't going to change this, other design decisions could.  Like if each actor was responsible for doing their own configuration control, but as I said my design didn't go this way, not that this could work.

 

Oh and my setup did have a cancel option, which just wouldn't send out the 1-to-N message that a setting was changed, and it would re-read the config file, and re-write the controls in the pages.  One other thing I forgot to mention is some times pages of the config, would rely on other pages of the config.  So say I had a page that had a Show Advanced Settings checkbox.  If this was on you wanted all the other pages to show the advanced settings if there were any.  So when I sent out this 1-to-N message to the actors telling them a config was updated, I would also have that message go to each of the pages, so that they could then re-read from the global the settings from all the other pages, so they could show or hide the advanced settings based on the last applied settings.  I used this same message to the pages if you canceled too, because a cancel may revert to some state where the UI in the page needs to be updated.  I've thought about cleaning this up and posting it, but since it isn't an NI Actor, it uses a decent amount of the reuse library which would need to be made generic or released.

 

Yes. the "advanced" or dependent configuration is not easily catered for by just blindly loading and saving FP controls.It would be a mistake to try and add logic to a generic API to cater for application specific dependencies.

 

I chose to have the basic load/save behaviour which is fine 8 times out of 10 and then use a query to update specific controls so it is a two step update for corner cases. It is very simple but does require a little bit of thought about naming your controls. The current query function only interrogates label names as a partial match so adding "Avanced_" to a control, for example, means you can achieve that behaviour. A slightly more complicated query would be nice across dialogues and in my personal version the default query string can be overriden but since I never get any feedback as to features people want or bug reports to drive another release; I haven't implemented it as yet. :P

Share this post


Link to post
Share on other sites

In case the OP wasn’t aware, there is an Actor Framework group on NI where there are more AF users who might respond.

 

 

This doesn't seem like a sensible approach, though. Waiting for message replies sounds like the wrong thing to do.

 

 

Waiting on things that are reliably quick is often the best thing to do, IMO, as it is often simpler.  

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Similar Content

    • By McQuillan
      Hi Everyone,
      I (re)watched James Powell's talk at GDevCon#2 about Application Design Around SQLite. I really like this idea as I have an application with lots of data (from serial devices and software configuration) that's all needed in several areas of the application (and external applications) and his talk was a 'light-bulb' moment where I thought I could have a centralized SQLite database that all the modules could access to select / update data.
      He said the database could be the 'model' in the model-view-controller design pattern because the database is very fast. So you can collect data in one actor and publish it directly to the DB, and have another actor read the data directly from the DB, with a benefit of having another application being able to view the data.
      Link to James' talk: https://www.youtube.com/watch?v=i4_l-UuWtPY&t=1241s)
       
      I created a basic proof of concept which launches N-processes to generate-data (publish to database) and others to act as a UI (read data from database and update configuration settings in the DB (like set-point)). However after launching a couple of processes I ran into  'Database is locked (error 5) ', and I realized 2 things, SQLite databases aren't magically able to have n-concurrent readers/writers , and I'm not using them right...(I hope).
      I've created a schematic (attached) to show what I did in the PoC (that was getting 'Database is locked (error 5)' errors).
      I'm a solo-developer (and SQLite first-timer*) and would really appreciate it if someone could look over the schematic and give me guidance on how it should be done. There's a lot more to the actual application, but I think once I understand the limitations of the DB I'll be able to work with it.
      *I've done SQL training courses.
      In the actual application, the UI and business logic are on two completely separate branches (I only connected them to a single actor for the PoC) 
      Some general questions / thoughts I had:
      Is the SQLite based application design something worth perusing / is it a sensible design choice? Instead of creating lots of tables (when I launch the actors) should I instead make separate databases? - to reduce the number of requests per DB? (I shouldn't think so... but worth asking) When generating data, I'm using UPDATE to change a single row in a table (current value), I'm then reading that single row in other areas of code. (Then if logging is needed, I create a trigger to copy the data to a separate table) Would it be better if I INSERT data and have the other modules read the max RowId for the current value and periodically delete rows? The more clones I had, the slower the UI seemed to update (should have been 10 times/second, but reduced to updating every 3 seconds). I was under the impression that you can do thousands of transactions per second, so I think I'm querying the DB inefficiently. The two main reasons why I like the database approach are:
      External applications will need to 'tap-into' the data, if they could get to it via an SQL query - that would be ideal. Data-logging is a big part of the application. Any advice you can give would be much appreciated.
      Cheers,
      Tom
      (I'm using quite a few reuse libraries so I can't easily share the code, however, if it would be beneficial, I could re-work the PoC to just use 'Core-LabVIEW' and James Powell's SQLite API)

    • By Ryan Vallieu
      I have seemingly found an issue with the shipping example code for Nested Malleable VIs.  Another user has verified that he saw the same behavior in 2019.
       
      I am working through the examples and the presentation from NIWeek 2019.  In running the Lesson 2b code (C:\Program Files (x86)\National Instruments\LabVIEW 2019\examples\Malleable VIs\Nested Malleable VIs) I found the Equals.vi in the class was not being leveraged and the search failed.  When I went to my LabVIEW 2018 machine and ran the Lesson 2b.vi the code worked to find the element by correctly leveraging the in-class Equals.vi.
      One difference I see is that in the 2018 example the Equal.vi is in the example folder with the code, and in 2019 the Equal.vi has been moved to VI.lib - otherwise the code looks to be the same.  The Equals.vi code looks identical, and the calling VIM look identical.  I posted on the LabVIEW NI.com forum here: 
      https://forums.ni.com/t5/LabVIEW/LabVIEW-2019-Malleable-VIs-Shipping-Examples-Lesson-2b-Nested/m-p/3966044/highlight/false#M1129678
       
      I am trying to determine what may have broken or changed between the implementation in 2018 and 2019, visually the code looks the same.
    • By Voklaif
      Hello all,
      I am programming with LabVIEW for around 2 years and was recently stumbled upon LVOOP.
      I am required to write a communication protocol to work with a micro-controller, which later will be also used for ATP and debug purposes.
      I want to build the program "correctly" from the beginning so it will be maintainable and flexible to additions and changes.
      My natural way of building a program would have been a queued state machine, with several loops, each loop is in charge of a different module (one for GUI obviously), but as I stated in the beginning, I want to use LVOOP.
      Does anyone have a LVOOP project I can use as reference? I've searched online and found some nice examples, but they are small and teach you the basic stuff.
      For me it's important to see the how to use the project tree wisely, where to place the classes, see the managing loop and to learn as much as possible before I create one of my own.
      Thanks in advance,
      Voklaif
    • By A Scottish moose
      Hello everyone,
      TL;DR - Any thoughts on if it's a good or bad idea to spin off an actor from a QMH framework?  I've got some library code that would be valuable but the project itself doesn't justify AF.
      I'm brainstorming ideas for a tester that I'll be building over the next few months. The project that I'm currently winding down is an Actor Framework test system that has come out really nice. Part of the project was an actor built to handle all of the DAQ and digital control.  The main actor spins it off an tells it when and what tasks to launch.  It send back data and confirms commands, uses Dynamic events to keep up with the generated signals, and uses actor tasks to ship the data back to the controller.  Works amazing. Nothing revolutionary for sure but very handy.
      This next project doesn't really need actor framework, it's much smaller and has a lot smaller list of requirements.  That being said I'm curious about integrating my DAQ actor (Dactor, because who can resist an amalgamation?!) into the project. Any thoughts on if it's a good or bad idea to spin off an actor from a QMH framework?  Is this even possible based on how the AF tree is designed to work?
      Thanks for reading!
      Tim
       
    • By GregFreeman
      I have an array of classes, let's call the object TestPass, of size 1 (but it is an array because it can scale out to multiple test passes). In this class, there is one other nested class which is not too complex, then various numeric and string fields to hold some private data. There is also an array of clusters. In this cluster there is a string, two XY pair clusters, and an integer. Not very confusing.
      This array of clusters gets fairly large, however, upwards of 80-100k elements. What I am finding is when I index the array of pass classes it is crazy slow. On the order of 30 ms. Doesn't seem like much, but we are indexing the array in our method to "Get Current Pass" which is used in various places throughout our code. This is adding potentially hours to our test time over the 80k devices we are testing. 
      So, I started digging. When I flatten the class to a string and get the length, it's 3 mb. But, when I run the function with the profiler is is allocating close to 20 mb of memory!
      My gut feel was that the string is causing the issues. So I removed the string from the cluster and the index time went to 0 ms. 
      Luckily we can normalize a bit and pull the strings out of the cluster since a lot of them are duplicates. But it makes our data model a bit uglier. 
      Has anyone seen these kind of performance issues before? I saw them in 2013 and 2017.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.