12-09-2015 05:45 AM
Hi,
I want to read the "parseSrvCmd" structure sent by a C program over TCP in LabVIEW. The "parseSrvCmd" is composed of two structures (_srv_BasicFlds and _srv_DataPkt)- c code is provided towards end of this post.
After searching through this forum, came to know that, the output string from TCP read vi function needs to be correctly typecast to match the C structure in terms of data types and pragma packing.
Can any one guide me, with the correct data types/ cluster elements to be used for typecasting- especially for
"char prmname[MAXDATA][DATALEN]"? What will be effect of pragma packing on the LabVIEW code, while trying to typecast/ separate the individual fields of cluster?
--------------------C code for Strucure ------------
#define MAXDATA 128
#define DATALEN 64
#define MSGLEN 128
#pragma pack(push,1)
typedef struct _srv_BasicFlds{
int seq;
float version;
short priority ;
short timeout ;
char subsysid[DATALEN];
char cmdname[DATALEN];
char timestamp[DATALEN];
char id[8];
} _srv_BasicFlds;
/* data information */
typedef struct _srv_DataPkt{
short numpkt;
char prmname[MAXDATA][DATALEN];
char prmvalue[MAXDATA][DATALEN];
} _srv_DataPkt;
typedef struct parseSrvCmd
{
_srv_BasicFlds cmdelem;
_srv_DataPkt data;
} parseSrvCmd ;
#pragma pack(pop)
12-09-2015 06:48 AM - edited 12-09-2015 06:50 AM
First the pragma pack(1) will cause the C compiler to pack everything maximally. This is also the LabVIEW default.
Second, the only valid datatype for "char elm[DATALEN]" that allows to directly typecast the bytestream into a LabVIEW cluster is another cluster with DATALEN (un)signed 8 bit integers. These are not normal C strings anyways but fixed size arrays, which get directly inlined in the C structure (which is the only way to specify a bytestream protocol in C type definitions without adding a special flatten and unflatten function in between which collects the various sparse data elements from pointers and packs them into a stream and vice versa.
After that you have to go through each of those byte arrays and convert them into a string and create a native LabVIEW data cluster which uses normal strings (or arrays for binary data). The length of the byte array can be defined by a different element in your structure or for strings usually is indicated by a NULL character.
Personally I often directly go through the bytestream and parse the different elements from it into the final LabVIEW data cluster which contains the correct datatypes such as strings, arrays, sub clusters and scalar elements.
12-09-2015 08:00 AM
12-09-2015 09:13 AM - edited 12-09-2015 09:15 AM
12-09-2015 09:39 AM
The problem you have is that you can't define a fixed length Array in a cluster type in LabVIEW.
The fixed length array have to be a cluster in LabVIEW.
LabVIEW should easily be able to convert the byte to a type every second. I think even if you manualy to through the bytes.
12-09-2015 11:13 AM
Thanks, I realised that. So the corrected cluster becomes as described below. Would like to know about the correctness of datatypes and lenth of the cluster elements as well.
Element 1: int seq >> U32
Element 2: float version >> SGL
Element 3: short priority >> U16
Element 4: short timeout >> U16
Element 5: char subsysid[DATALEN] >> U8 cluster [64 elements] (DATALEN is 64)
Element 6: char cmdname[DATALEN] >> U8 cluster [64 elements]
Element 7: char timestamp[DATALEN] >> U8 cluster [64 elements]
Element 8: char id [8] >> U8 cluster [64 elements]
Element 9: short numpkt >> U16
Element 10 to Element 138: char prmname[MAXDATA][DATALEN] >>>> U8 cluster [64 elements] (representing 128 rows of this 2D array sent in a structure and DATALEN = 64)
Element 139 to Element 266: char prmvalue[MAXDATA][DATALEN] >>>> U8 cluster [64 elements] (representing 128 rows of this 2D array sent in a structure and DATALEN = 64)
12-09-2015 01:58 PM
@ITA wrote:
Thanks, I realised that. So the corrected cluster becomes as described below. Would like to know about the correctness of datatypes and lenth of the cluster elements as well.
Element 1: int seq >> I32
Element 2: float version >> SGL
Element 3: short priority >> I16
Element 4: short timeout >> I16
Element 5: char subsysid[DATALEN] >> U8 cluster [64 elements] (DATALEN is 64)
Element 6: char cmdname[DATALEN] >> U8 cluster [64 elements]
Element 7: char timestamp[DATALEN] >> U8 cluster [64 elements]
Element 8: char id [8] >> U8 cluster [8 elements]
Element 9: short numpkt >> I16
Element 10 to Element 8202: char prmname[MAXDATA][DATALEN] >>>> U8 cluster [64*128 = 8192 elements] (representing 128 rows of this 2D array sent in a structure and DATALEN = 64)
Element 8202 to Element 16484: char prmvalue[MAXDATA][DATALEN] >>>> U8 cluster [64*128 = 8192 elements] (representing 128 rows of this 2D array sent in a structure and DATALEN = 64)
Quite a few errors!! And all except the U(nsigned) to I(nteger) mismatches definitely fatal for reading the right data.
Especially for the last 2 elements I would not include them in the typecast but process them seperately.
12-10-2015 03:20 AM - edited 12-10-2015 03:31 AM
12-10-2015 04:12 AM - edited 12-10-2015 04:16 AM
Your super mega pronto saurus cluster is going to give you very much trouble. LabVIEW maintains a complete recursive type description of all its datatypes and such a cluster causes a typedescriptor of many kB length that LabVIEW repeatedly has to parse every time you do some edit operation on the diagram. Not a good idea at all and anyhow not really helpful.
I would do it more along these lines as attached. There are still many open ends so far that I can not fill in for you. The strings that get returned may not always be 64 or 8 characters long but shorter, having a NULL character as termination indication. So you might need to create a subVI that goes through each character byte by byte until it sees a NULL byte.
I also assumed that numpkt is the number of effectively available data packets in the stream rather than always 128. That may or may not be correct, I don't know but from other experiences it seems like a good guess.
12-10-2015 11:06 AM
Thank you for your help- I am able to read the structures.
But facing a different problem now. How do I determine the end of structure/ start of structure, while I am trying to read it over TCP? There are no special provisions made in the packet/structure to determine the start / end of structure. Any suggestions on how to tackle this issue?