Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Integrating AF & LVOOP with hardware

Solved!
Go to solution

Question: how do you handle subclasses in configuration?  I very often have cases where some subcomponent can be one of multiple subtypes, each with different config info.  A common example is hardware abstraction, but anything that involves a choice of child classes has the same issue.  The config info will be a different structure based on child class. Maybe one child uses TCP and has an IP address, while the other has a Com Port and Baud Rate, say. 

 

How do you handle this with your LabVIEW Clusters?   How do you store config info from subclasses?

0 Kudos
Message 81 of 88
(1,547 Views)

@Dmitry wrote:

As to 'json-to-whatever' converter vs 'LVCluster-to-whatever' converter: your choice depends on whether you are OK with weak type-checking or have a preference for strong type-checking.

 


Just circles me back to my original point: you don't have strong type-checking through the storage format, and thus still do all the weak type checking.  

0 Kudos
Message 82 of 88
(1,544 Views)

 


@drjdpowell wrote:

Question: how do you handle subclasses in configuration?  I very often have cases where some subcomponent can be one of multiple subtypes, each with different config info.  A common example is hardware abstraction, but anything that involves a choice of child classes has the same issue.  The config info will be a different structure based on child class. Maybe one child uses TCP and has an IP address, while the other has a Com Port and Baud Rate, say. 

 

How do you handle this with your LabVIEW Clusters?   How do you store config info from subclasses?


Easily 🙂

 

  1. Assembler class knows everything about the application (it is application specific code). One of its responsibilities is to create objects of the right subtypes - so it is statically linked to all supported subtypes anyway
  2. Assembler configuration 'supercluster' has configuration subclusters for all supported classes/subclasses and loads/saves such supercluster on application startup/shutdown
  3. Assembler configuration also has a 'section' that describes which subclasses to create on startup - so in the BringUp method it has case structures for each group of subclasses. In each case frame it unbundles the right configuration subcluster and passes it to it's respective class constructor. Unbundle is a strong type check (else you get a broken wire)
  4. You can also add some code to replace an object of one subtype with a [newly created] object of another subtype in case you need switching device drivers at runtime

This approach does not work for 'dynamic plug-in' applications that dynamically load subslass code (plugins) from a known folder hierarchy at runtime. For this type of application one needs to use some flavor of a Service Locator.

 

0 Kudos
Message 83 of 88
(1,523 Views)

 


@drjdpowell wrote:

@Dmitry wrote:

As to 'json-to-whatever' converter vs 'LVCluster-to-whatever' converter: your choice depends on whether you are OK with weak type-checking or have a preference for strong type-checking.

 


Just circles me back to my original point: you don't have strong type-checking through the storage format, and thus still do all the weak type checking.  


Correct. But in my case there are only two weak type-check call sites per application. In case when a class implements Loading/Saving its own configuration it is two weak type-check call sites per class.

 

 

0 Kudos
Message 84 of 88
(1,521 Views)

Ah, so to follow my example, you would have both an IP address AND a Com Port and Baud Rate.

 

Re the single versus many call sites, I'm not sure that means anything, in that it isn't preventing any errors.

0 Kudos
Message 85 of 88
(1,504 Views)

@drjdpowell wrote:

Ah, so to follow my example, you would have both an IP address AND a Com Port and Baud Rate.

 


Yes. But in separate clusters - each subclass would have its entire configuration cluster stored in the application configuration supercluster.

 

0 Kudos
Message 86 of 88
(1,497 Views)

@drjdpowell wrote:

@WavePacket wrote:

@drjdpowell wrote:

@WavePacket wrote:

@drjdpowell wrote:

Why do you have a "database actor"?  Databases are a lot more sophisticated than some dumb hardware.  They support multiple clients with transactions and ACID compliance.  Why not use them directly?


"Why" is that there are a few times where I want the asynchronous behavior. For example, there is a software where I want to populate query results as they come. The user is likely interested in the latest results but could infrequently be interested in old data. So I want to present the newest results first, but asynchronously continue to fill in old results as they come back. The query is long enough that I don't want to make the user wait for all results to come back.

 

Another possibility is that as a test proceeds, I want to asynchronously be asking the database as we go along if the test results are normal (but allow the test to continue until the database responds with a warning). Kind of like an asynch background check of the results.

 


Databases are already asynchronous.  More capably asynchronous that you Actor is.  Databases can generally support multiple Readers and Writers at the same time, and have a Transaction system to keep things straight.  Your Database Actor is not able to do these things, and by putting a single Actor as gate-keeper to the Database you are significantly reducing the asynchronous capability of your App, or at least you are forced to reinvent the wheel.


I'm familiar with concurrency in databases. What I need though is asynchronous behavior in my app, but from the databases perspctive it might not need to the asynchronous connections. If I desired asynchronous behavior in my app, and asynchronous database connections would your suggestion be something like launch many copies of async VIs to launch more than one query simultaneously?


As an example, let's say we have:

Actors A, B, and C that collect data and save to the database.

Actor D that analyses the recent data and saves results in the database.

Actor E that watches the database to display if results seem normal.

Actor F that displays recent results from the db.

Actor F that displays long-term trends in the db.

 

All these Actors can independently talk to the database.  So what is your "Database Actor" for?  What does "I need asynchronous behavior in my app" even mean in this context, given that all these Actors have clear and simple single-purpose roles?  Actor F, for example, may have to wait a bit for it's long-term trends Query, but it doesn't have anything else to do while it is waiting, so why would it need an asynchronous db query?


So I was rereading this thread again...and realized I got distracted by other topics and never closed off this sub-topic.

 

My desire for a "database actor" was that it was meant to be a reusable actor used for all cases A through F. Potentially, that desire for generality directly led to my problem of "but where does the specific syntax".

 

So now I'm thinking:

  1. write actors which have the specific SQL syntax in them and and therefore are not reusable. I think this is your suggestion in the last quote.
  2. Or, I might consider having a "generic" database actor, and actors A through F launch the generic database actor as a sub-actor? These A through F actors are "adapters" between the test-code and the SQL actor.

 


------------------------------------------------------------------------------------

Please join the conversation to keep LabVIEW relevant for future engineers. Price hikes plus SaaS model has many current engineers seriously concerned...

Read the Conversation Here, LabVIEW-subscription-model-for-2022
0 Kudos
Message 87 of 88
(1,450 Views)

@WavePacket wrote:

@BertMcMahan wrote:

...


...

 

Mind if we also discuss a situation where the hardware interactions are rather test-station specific? This means that multiple test stations seem unlikely to be able to inherit the same interfaces.

 

As an example, one of my "hardware" actors is a database, and multiple other softwares actors have database needs which are rather specific (i.e., I need this data analyzed in this way, from the previous test). So each test station will have different database syntax.

 

So I'm kind of at a loss for how to separate the concerns between the multiple software actors and the single database actor in particular. Some options (maybe the nicest option is not even among this list...?):

  1. The softwares' actors supply the database queries they need
    • (But as an example, this seems to be analogous to having Multimeter VISA commands being supplied individual test softwares, which isn't a good architecture).
  2. ...

So to reply to my past self (a psychologist might have word about whether that's normal or not...). I'm getting less worried about #1. After the dust settles, if a test software interacts with a database, somewhere that dependency is going to rear its head and has to be injected. I think the way forward is to make the interfaces as generic as possible, and then separate as much of the SQL syntax as reasonable.

 

For example, these interfaces could be wrappers of dynamic SQL where at runtime the parameters are supplied. As a specific case, I could have an interface which is for selecting all data from a table, and the tablename is selected at runtime. That seems reasonable.

 

That's somewhat equivalent I suppose of wanting a power measurement but first I have to tell you the wavelength of light. All the VISA syntax is under the hood, but I do need to tell you the wavelength parameter.


------------------------------------------------------------------------------------

Please join the conversation to keep LabVIEW relevant for future engineers. Price hikes plus SaaS model has many current engineers seriously concerned...

Read the Conversation Here, LabVIEW-subscription-model-for-2022
0 Kudos
Message 88 of 88
(1,450 Views)