Jump to content

Organizing Actors for a hardware interface


Recommended Posts

I'm somewhat new to Actor framework and this is my first major project using it. I've completed a few simple Actors before and integrated them into larger applications.

 

I am communicating with a device over Ethernet. A proprietary program takes in ASCII commands and passes them to the device. Data is returned along the same TCP connection as ASCII strings.

 

I want to display the data to the user in a UI. In the future, the proprietary communication program may be swapped out for a custom in-house program. There are likely to be different UIs in the future.

 

I decided to create 3 Actors: a Hardware Interface / Listener actor, a Controller actor, and a UI actor. I want to keep communication between the three Actors simple and consistent, so potential future Actors are able to handle the same messages. The Listener and UI actors may be substituted for other actors in the future (a certainty in the case of the UI actor).

 

A critical task of the UI is to be able to display the parameters/settings of the device. There are several dozen different settings. The UI is interested in displaying some of them as indicators, issuing warnings depending on other parameters, and ignoring other updates. The UI's response to a specific parameter would change depending on which UI is being used.

 

What I'm struggling with is this:

  1. Which Actor should store the hardware's current parameters/settings?
  2. Should there be multiple copies of the hardware's current settings in each Actor?
  3. How should the parameters be passed around? Should there be an abstract Parameter class?
  4. If I used an abstract Parameter class, would dynamic dispatch be the best way to handle different UI reactions?

I'm afraid of coupling Actors too tightly together. On the other hand, it's not clear to me where the Parameter data should be stored, because it seems like the Controller and UI would need to have access to it. Should it be stored in the Controller and passed up to UI as needed?

 

If anyone has any thoughts/advice, I'd greatly appreciate it.

Link to comment
What I'm struggling with is this:
  1. Which Actor should store the hardware's current parameters/settings?
  2. Should there be multiple copies of the hardware's current settings in each Actor?
  3. How should the parameters be passed around? Should there be an abstract Parameter class?
  4. If I used an abstract Parameter class, would dynamic dispatch be the best way to handle different UI reactions?

I'm afraid of coupling Actors too tightly together. On the other hand, it's not clear to me where the Parameter data should be stored, because it seems like the Controller and UI would need to have access to it. Should it be stored in the Controller and passed up to UI as needed?

 

If anyone has any thoughts/advice, I'd greatly appreciate it.

I am not an expert at the Actor Framework.  I've only used it a few times, so I'll answer the easy ones in my opinion. 

 

1) The Hardware Actor should have the hardware settings.

2) Is it necessarily for the other Actors to know the settings?  If not then they don't need to know.  If you want the other actors to know I would recommend using a VIG where only the Hardware Actor performs writes, and the other Actors only perform reads.  You could get away with this by using two separate VIs that call the same VIG, one with a constant for write the other for a constant for read.  Then you can find all instances of writing/reading to verify that only the correct Actors are writing to it.  If you have a VIG being written to in multiple places at once there is no way to maintain the correct data (just like a normal global).

Link to comment
1) The Hardware Actor should have the hardware settings.

 

This makes sense, but does that mean EVERY time the UI queries a setting, it has to go through the Controller to query the Hardware Actor?

 

2) Is it necessarily for the other Actors to know the settings?  If not then they don't need to know.  If you want the other actors to know I would recommend using a VIG where only the Hardware Actor performs writes, and the other Actors only perform reads.  You could get away with this by using two separate VIs that call the same VIG, one with a constant for write the other for a constant for read.  Then you can find all instances of writing/reading to verify that only the correct Actors are writing to it.  If you have a VIG being written to in multiple places at once there is no way to maintain the correct data (just like a normal global).

 

I definitely don't want to use a functional global (Is that what you mean by VIG?). I don't have a lot of experience with OOP, but so far the couple times I've tried mixing in a functional global have made it hard to maintain in the future. If I want to swap new Actors in, then would they ALL rely on this functional global? Sounds problematic...

 

I think there needs to be some logic in the Controller to check for constraint problems, for problems attempting to set Hardware values. For example, the UI tries to set Resistance = 5, but the command fails. I want to be able to capture that sort of thing at the Controller.

 

For those things, it would be very handy to have access to ALL the Hardware settings right away. It COULD ping the Hardware Interface for those settings as needed... I don't know. This is very new to me, too.

Link to comment

<blockquote class='ipsBlockquote'data-author="Mike Le" data-cid="101054" data-time="1359502271"><p>

This makes sense, but does that mean EVERY time the UI queries a setting, it has to go through the Controller to query the Hardware Actor?

</p></blockquote>

The preferred way to think about your actors is that they post information, rather than requesting it. That turns your issue around slightly:<br />

- The hardware actor stores it's own settings. If they change then it notifies someone who cares... probably the controller, which in turn notifies the UI.<br />

- The UI then does what it wants with the information.

  • Like 1
Link to comment
I definitely don't want to use a functional global (Is that what you mean by VIG?). I don't have a lot of experience with OOP, but so far the couple times I've tried mixing in a functional global have made it hard to maintain in the future. If I want to swap new Actors in, then would they ALL rely on this functional global? Sounds problematic...

Yes, the terminology is slightly different depending on who you ask, but for many cases VIG = Functional Global = LV2 Global.

 

I didn't know that the Actor Framework was OO based.  Knowing that I also would be careful about using a VIG to maintain settings, but as I said before it could have another layer on top using a sub VI called "Get Settings" which all it does it read a VIG which maybe a little cleaner.

Link to comment

If you’re following the Actor Model then actors should not share data by-reference.  This means that different Actors often must either keep a copy of the info they need, or request the info from other actors when needed (the first option is probably best).

 

For your “Resistance=5” example, the UI could send a “Set Resistance Request” Message, and the Controller would check the value against its copy of the parameters.  If invalid, it would sent a “Resistance=<old> value” back to the UI, followed by some message to display a warning to the User.  If valid, it would send a “Set Resistance” message to the Hardware Actor.  The Hardware would then send a “Resistance Update” message to the Controller, who would send a copy to the UI.

Link to comment
For those things, it would be very handy to have access to ALL the Hardware settings right away. It COULD ping the Hardware Interface for those settings as needed... I don't know. This is very new to me, too.
Having dealt a lot with hardware systems. There were a few conclusions I cam to quite a few years ago.

That is that with hardware settings, you should always rely on the device to tell you what you can and can't do. If you start restricting user input values before sending to the device, you very quickly end up trying to replicate the device logic which can get very complex. With this in mind, it becomes just a case of setting max/min values to the controls. Additionally, most modern devices give readable error responses, so usually you only need to bubble them back to the UI.

Similarly. When it comes to device state. You should not try and maintain it in the software, rather, interrogate any state information as and when you need it. Maintaining device state in the software will vastly over complicate your code and lead to hard-to-debug disparities between the actual device state and that of your software. This situation is totally avoidable and means that very simple recovery procedures can be facilitated without complex code and the code can reflect state without logic.

If you bear in mind these "rules-of-thumb". You devices will do all the hard-work and greatly simplify your code as well as being far more robust.

  • Like 1
Link to comment
 When it comes to device state. You should not try and maintain it in the software, rather, interrogate any state information as and when you need it. Maintaining device state in the software will vastly over complicate your code and lead to hard-to-debug disparities between the actual device state and that of your software. This situation is totally avoidable and means that very simple recovery procedures can be facilitated without complex code and the code can reflect state without logic.

 

This is excellent advice. I knew I was complicating the system, but wasn't sure what to do about it. I think the guidelines you've laid out will help a great deal.

 

Thanks!

Link to comment

Agree with Intaris, though I prefer push over pull:

rather, interrogate any state information as and when you need it

I don't encourage interrogating the HW. Instead let it push changes up to the UI when they happen. The UI just announces "I am connecting" or "I am disconnecting". After that, it is the HW's job to tell the UI about state changes. The benefit here is that you, the designer, do not ever get in the mindset of your UI holding and waiting for information from the HW, which leads to long pauses in your UI responses.

Link to comment
Agree with Intaris, though I prefer push over pull:

I don't encourage interrogating the HW. Instead let it push changes up to the UI when they happen. The UI just announces "I am connecting" or "I am disconnecting". After that, it is the HW's job to tell the UI about state changes. The benefit here is that you, the designer, do not ever get in the mindset of your UI holding and waiting for information from the HW, which leads to long pauses in your UI responses.

Unless your hardware uses push streaming (rare as rocking-horse droppings). The hardware cannot tell the UI since it will be CMD->RESP.

Link to comment
Unless your hardware uses push streaming (rare as rocking-horse droppings). The hardware cannot tell the UI since it will be CMD->RESP.

 

One can have a “Hardware” actor, that is the only process to actually communicate with the actual hardware.  That actor pulls from the hardware, but pushes status changes to other actors.  [AQ may be thinking of this “Hardware” actor rather than the actual hardware.]

Link to comment
One can have a “Hardware” actor, that is the only process to actually communicate with the actual hardware.  That actor pulls from the hardware, but pushes status changes to other actors.  [AQ may be thinking of this “Hardware” actor rather than the actual hardware.]

Indeed. So you are getting the status directly from the device as and when you need it rather than "remembering" state in the software. It doesn't matter what the method of transmission through the software is (actors, events, queues, notifiers or whatever-a good point to again whinge about not being able to hook up VISA refs to the event structure ;) ).

Edited by ShaunR
Link to comment
One can have a “Hardware” actor, that is the only process to actually communicate with the actual hardware.  That actor pulls from the hardware, but pushes status changes to other actors.  [AQ may be thinking of this “Hardware” actor rather than the actual hardware.]

Sometimes I would suggest such a proxy, but there are some pieces of HW that behave more like streams of status updates: a sensor that continually sends back data, or a robotic arm that you give it a final X, Y, Z coordinate to reach and it streams back to you the ongoing "here's where I am now" info, rather than you polling the HW continuously for "where are you now? how 'bout now?"

 

If I had to build a proxy between the UI and the actual HW to make that happen, that would be my first choice of architecture, all other things being equal and no other information about the system. Essentially, I prefer to get to "push" as quick as possible, whatever software layers are required to achieve that. I find that it gives a more responsive system overall.

 

And, for the record, this isn't just Actor Framework. This is any sort of "here's the UI process and over here is the HW process". So "actor" as a model of the system, not as a particular instance of Actor.lvclass.

Link to comment
And, for the record, this isn't just Actor Framework. This is any sort of "here's the UI process and over here is the HW process". So "actor" as a model of the system, not as a particular instance of Actor.lvclass.

 

I also agree with this because I have experienced it in non-LVOOP it simplifies debugging and design; but what if you have a HAL.lvclass being stimulated by that "HW process" and you don't want to fork wire; but when you have a situation where you want to stream more than one channel up to the GUI/Controller simultaneously then what should be done? I am relating it with my HAL.lvclass:

 

http://lavag.org/topic/16510-dvrs-within-classes/

Link to comment

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.

×
×
  • Create New...

Important Information

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