10-01-2015 08:15 AM
I am developing an Actor Framework based application that sometimes needs access to hardware resources. For now, I will just keep it simple and say that the application (on a laptop) needs to monitoring temperature in 1 or more machines. The application would maintain the communication and always attempt to initialize or recover without operator intervention. A system configuration would say how many channels and where they are. The application would be able to scale up or down.
This all sounds resonable, but I am hung up on one issue. I would like to just create a temperature class and spin one up for every channel. The problem is that I am talking to multi-channel temperature controllers over Modbus and/or Modbus/TCP. This means that multiple groups of channels will share the same communication bus (either by serial port or by IP address). My initial solution to get something going was to contain each communication bus in a DVR in a class, open communication, and pass it into each temperature constructor that shares it. This works fine until something goes wrong with the connection. Note that a singleton doesn't seem appropriate for this because there could be multiple groups of temperature devices, so I would need multiple shared resources.
Now what I am missing is a concept for having the communication maintain itself and provide status to the temperature instances and the application. What happens if the connection goes down (someone walks away with their laptop)?. What happens when the connection is available again (someone plugs in the ethernet cable)? I would also like to here thoughts on whether it is appropriate to have the temperature instances and/or the communication busses be Actors (as opposed to being directly handled by a different actor).
Thanks for any suggestions,
Greg
10-01-2015 09:51 AM
It seems like you are thinking about the correct things.
To answer your list of questions with a question: What do you want to happen? These are all cases that you need to define, design, and test to validate. Customer, System and Engineering requirements should drive your design.
For example: "a remote system shall connect to central system when available"
It sounds like you definitely need something to manage connections. Perhaps something Publish/Subscribe with an array of enqueuers and message types.
It sounds like data might be different for each machine, so you may want to think of a way to either encapsulate it or make it generic for consuption.
I don't think I would mix AF and DVRs. Actors own their data. If you need to share data you send a message. If you need central storage of all data then you have all actors send data messages to the storage actor.
Good luck,
Casey
Phoenix, LLC
CLA, LabVIEW Champion
Check Out the Software Engineering Processes, Architecture, and Design track at NIWeek. 2018 I guarantee you will learn things you can use daily! I will be presenting!
10-02-2015 12:52 PM
Yes, there is a lot to think about. I would like to understand what my options are for sending my data to a central storage. In the past, this would be easy through FGVs or some similar method. If each temperature channel is treated as an Actor, what is a good method to route the result to the central storage? I can think of zero-coupling or events, but it seems like this would need maintenance and not be as flexible (in the context of identifying every channel). Another approach could be to bundle my data with an identifier? When each Actor is launched, it could be assigned the identifier and then the central storage could find a way to handle this (Type of instrument, type of result, channel name, value). Maybe a result class from which different results types inherit from.... Have I just missed an easy solution for this? My temperature actors can't just enque a result to the caller because the caller won't know where it came from (or could it?).
10-02-2015 01:03 PM
I have a logger class (Actor) that is overriden with a telemetry logger. All my actors can send telemetry to that logger. I hand out the EnQr at startup. I keep track of the telemetry source and type with a dotted string. Ex:
dutModel.dutSN.rackID.HWID.HWCh.type.friendlyName
Some of this info comes from the input configuration data. By capturing all the info into a single dotted string, it gives a complete picture how and where the data was generated, no matter the source or type. The dotted string is paired with the actual data value of course and a time stamp, either in a cluster or a class.
My telemetry logger can then choose how it wants to log (i.e., I can create any sort of child override to log to text files or csv or database or you name it). I needed that flexibility because I have to start easy (say text files) and when I get some more time work my way into a fully parametric database. That's one of the beauties of AF, being extensible without changing previous work.
10-02-2015 01:13 PM
I have moved away from identifiers and operate completely with different children message classes of the zero coupled message.
You do enqueue to the caller.
When the caller launches the nested actor it provides a child of the zero coupled message class. If you need to store data in different places you have to create methods for storing the data (maybe just a write accessor) and then you need to create a message for that method and make the message inherit from the zero coupled message. You repeat this for each different place you are going to store data.
Note: these children messages don't store the data, the parent class does. Then in the Do.vi you need an accessor to read the data from the parent class and use that data as input to your method within Do.vi.
Phoenix, LLC
CLA, LabVIEW Champion
Check Out the Software Engineering Processes, Architecture, and Design track at NIWeek. 2018 I guarantee you will learn things you can use daily! I will be presenting!
10-02-2015 01:43 PM
A quick question about the zero coupled solution. If a caller had 2 nested Temperature actors there would be 2 overides which I think need 2 methods to back them up. By passing the concrete message at launch, then Temperature can send a message to the proper method. Each method would already know where the data came from so the Temperature actor wouldn't need to.
My question or concern comes from scaling. If my application decides there will be 10 channels or 20 channels by changing the configuration, I don't want to have to manually handle this. That would leave me with a generic response message which at that point I think it would need to identify itself.