02-07-2017 03:28 AM
I've finally knocked up a simplified version of what I'm currently doing (See attached .jpg). On the right hand side are the Init functions, the Message function calls the appropriate Message1 or Message2 function dependant on the contents of the first byte in the message. The top left vi is extracting and plotting data using the MessageName and FieldName strings passed in and the bottom left vi is Message1's version of the GetValueFromFieldName which uses a reference to a cluster control containing all the fields in the message, and then loops through all the controls within this cluster until the FieldName passed in matches the current control's label. The value of this control is then cast to a double and returned. The code for this vi would be virtually identical for each Message, but because I'm unbundling a specific control from the class, and then using this as a control reference, I need to duplicate this for every message I create (currently I've got around 20 messages, with the intention to add many more in the future). There is also another vi not shown, similar to the GetValueFromFieldName which returns an array of strings of all the fieldnames in the message passed in. Again, this vi has to be duplicated for each message. Is there a way of moving this code into the parent class and avoid this duplication (and the additional effort each time a new message is created)?
P.S. Just noticed the GetValueFromFieldName should have a Flat Sequence to force the control value property node to be executed after the class unbundle - looks like it currently works by relying on the unbundle being quicker than the looping until the control label matches...
02-07-2017 08:46 AM
Couple of thoughts for you to consider...
Message.lvclass:Init.vi
Is deciding which calls type it will invoke based on the first byte.
1) Adding more message type will require modifying that VI for each message type you add.
If you assigned the work to "Message1" or "Message2" then you can pass the message to an instance of each child type and let the child decide if that message it is responsible for. The method could return a boolean say "Got It!" so you can terminate teh loop iterating through the various message types. That way new messages can be added on the fly and the parrent does not have to change.
2) Using control refs will kill your performance. They require the UI thread so you will be thread swapping.
3) if you cast teh ref coming from the array as a numeric ref type yu do not need the from variant. But you should not be using control resf anyway...
4) Type def'd clusters are prefered over non-type-def'd ...
5) Type def'd clusters should/could be replaced with classes. That will allow for over-riding the data types.
6) If you had a method for each field that you are trying to extract from the message, they could grab their own data rather than assigining that work to the caller.
Just trying to help,
Ben
02-07-2017 09:38 AM
Thanks once again for getting back to me.
1) I don't understand why it would be better to write code in each child message class to return whether or not the data passed in is of the correct type - again I'd be duplicating the check on the first byte in all child classes rather than doing the check once at the parent level and deciding which child class to instantiate. Also, wouldn't I have to modify the parent class if I added a new message so it would attempt to instantiate the new message too? Or is the loop iterating through the message types not in the parent init?
2) My displaying of the graph is taking quite a while...
3) In my actual code the field may be an integer, double or boolean, so I attempt to convert the variant to each type in turn, then convert to a double to plot on the graph (with a boolean converted to 0.0 or 1.0). Out of interest though, is the cast to more specific on the reference better performance-wise than the convert variant vi on the data?
4) Again in the actual code the cluster is a type-def.
5) My Message classes only comprise that cluster aleady, no? How / why would I create a Class for the data the Message class contains? How can I over-ride a data type? I thought I could only override class methods.
6) If I added a method for each field, that would again mean a lot of code duplication. Furthermore, how would I call the correct accessor method at runtime, based on the user's selection. The only way I could think of would be to add case statements for every field, again resulting in some laborious coding and the need to add a case for every field each time a message was added.
Thanks once again for your time.
02-07-2017 01:12 PM - edited 02-07-2017 01:12 PM
Aside from the parent message class there is only one Over-Ride VI in each of two child classes "Init" which defines the name of the message packet type, the code number that ID's the packet type, and the offsets where the data will be found in the packet.
Adding more packet types only requiring cloning one of the child classes and adjusting the Init for the new message type.
Ben
Re: poor performance ... see my note above about control refs and the UI thread.