LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

LabVIEW class based messages

I've implemented a class based approach to storing messages read in from a file, with a top level Message class containing data which all the messages have e.g. message length, timestamp, message number, header byte, and child classes of each specific message. Each message class has an init method which converts an array of bytes into a cluster containing the fields which that message contains. E.g. byte 3 of one message may represent a voltage, whereas byte 3 of another message may represent temperature. The first byte of all the messages is a header byte which determines which message type the message is. The initial method for the parent class therefore looks at this byte before determining which of the child class init methods to call. This is all working fine, and I can read a file full of these messages and store them in an array of type Message (even though they're really an array of different child class types). Im now looking to be able to plot timestamp against field for any of the fields in any of the messages - the only way I can see to do this is by creating an accessor for each field for each message which would be very time consuming, and if I added further messages I would have to repeat the process. I want to give the user a drop down box of all the messages types in the file, and then another drop down which adapts to show the fields in the message type selected, finally plotting that field against its timestamp in a waveform.

0 Kudos
Message 1 of 14
(3,965 Views)

@redfrank wrote:

... - the only way I can see to do this is by creating an accessor for each field for each message which would be very time consuming, and if I added further messages I would have to repeat the process. I want to give the user a drop down box of all the messages types in the file, and then another drop down which adapts to show the fields in the message type selected, finally plotting that field against its timestamp in a waveform.

 

 


If the timestamp is located at the same offest for each message (child class) you need only implement the method in the Parent Class method.

 

If some of the meesage types have the time stamp elsewhere you can create over-rides in the child class to acces the timestamp field.

 

I do not follow you beyond that so expound a bit and maybe offer a image or two that will help us understand what your question may be.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 2 of 14
(3,924 Views)

Thanks for the getting back to me and I appreciate without the block diagrams it may be difficult to appreciate what I'm attempting to describe. I was on the train when I knocked up the first post and am at home without access to the code just now - I may be able to knock up some sample code over the weekend if I've got a spare minute. The timestamp isn't part of the message, but is on each line of the file I'm reading, and so is present no matter what message type. The field e.g. voltage / temperature etc is present only in one of the messages. I want some code that first of all loops through each message in an array of messages and tests for message type. This can be done using the GetClassName VI (not sure if that's the exact name) and testing that against a string retrieved from a drop-down list of messages. I then want to use a second drop down list of field types to specify which field to retrieve from the chosen message e.g. "voltage", and then get the value of that field from the chosen message. The loop would then give me an array of timestamps / values to plot. My message classes all contain a cluster containing each of the field controls, and I can create a method for each message class which, given a string, returns the value of the field that has that label by looping through the Controls[] property node of the cluster. Also the population of the list fields in the drop down enum can be done by creating a method which returns an array of the labels returned from the controls[] property node. Both these solutions mean creating almost identical code in each message class, when it feels like a method they could all inherit from in the parent class should be possible, and would reduce code duplication and make extending the classes with new message types easier. Thanks once again.

0 Kudos
Message 3 of 14
(3,909 Views)

@redfrank wrote:

Both these solutions mean creating almost identical code in each message class, when it feels like a method they could all inherit from in the parent class should be possible, and would reduce code duplication and make extending the classes with new message types easier. Thanks once again.


I don't see why you have to duplicate the code.  Why can't you just have the parent class hold the timestamp and then any classes the inherit from it will have access to it.  You just have to make the accessor for the parent class.  One of us is missing something really obvious.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 4 of 14
(3,900 Views)

Thinking out loud fix what I get wrong...

 

In parent class there is a method "get filed names". An over-ride in each child returns the feilds offered by the child class.

 

Those field names are used to populate drop down to choose.

 

Once a user selects a field name the index is used to get the child class that offers that field.

 

Attempt to cast each element in array as teh seelcted child class and those that do not return an error are entries of that type.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 5 of 14
(3,892 Views)

Hopefully it's me missing the obvious! So I'm storing all my messages as type Message rather than the child types Message1 and Message2 etc. Say Message1 contains a Voltage field and Message2 contains a Temperature field. I want the user to be able to select a message and then a field (resolved at runtime) e.g.Voltage and the code will loop through the array testing for the correct message and then the correct field, and return an array of values. Firstly my code will, for each message need to determine what child type it is, cast it to that more specific type,then call a method that returns the value for the correct field. If I was using normal accessors I'd have to create a case statement for each message type and each field to know which accessor to call. I've avoided that by using property nodes to return a list of control refs, but as I said I need to duplicate this for each of Message1, Message2 etc. What I'm after is some way of allowing the user at runtime to select any field from any message. I may be going about this completely the wrong way - is there a way of adapting a control at runtime to a different typedef / class control?

0 Kudos
Message 6 of 14
(3,891 Views)

Look at what I outlined above. The only I left out was for each entry in your array of class Message that casts without error as the child class selcted by ythe field name drop down you pass it to a method called "get value" of class Message that is is over-riden by the child class.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 7 of 14
(3,889 Views)

Hi Ben, previous post was before I had read your reply. That's pretty much what I've already got although I don't attempt to cast to the child class, I use a built in VI called GetLVclassName and compare that with the string from the enum. However it's the next step of extracting the correct field from the message, to be determined at runtime, that I'm trying to work out. Ideally I want a method in the parent class called GetValueOfFieldByString, and not have to override it for each message type. I suspect it's not possible as the parent can't access child data, right? Maybe I'm missing something about OOP - this is the most I've ever perserved with it and it just seems very restrictive without offering too many benefits as I always seem to come against a brick wall of something I think should be possible. As an aside, having to create an accessor for parent properties for them to be available in child classes seems insane to me. What then differentiates them from non children who could also call the same accessor? Anyway, I feel it must be me as OOP is so prevalent!

0 Kudos
Message 8 of 14
(3,878 Views)

While I don't like needing an accessor to read inherited properties, the answer to your question is pretty easy.

 

If you're trying to access one of your own properties that is inherited, you make the accessor private.  Then, only objects of that class can use it.

 

If you're trying to access a parent's property, make the accessor VI protected.  Then, only the parent class and its children can access it.

 

That's what keeps it from being accessed by non-children.  You can find these options in "Access Scope"

0 Kudos
Message 9 of 14
(3,846 Views)

Yeah, I did read you can stop non-children from having access to accessors by making them private but my gripe is with having to for children, not with preventing other stuff from accessing them (although yes this ability is what differentiates children from non-children). I've inherited blue eyes from my parents but you can tell that by looking at my eyes, not by asking my parents what colour my eyes are... If that's not stretching the analogy of inheritance somewhat!

0 Kudos
Message 10 of 14
(3,843 Views)