LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Sending Data from LabVIEW over TCP to read in a C Structure

Solved!
Go to solution

I want to send the data over TCP to the application written in C. The Application in C, intends to read this as a "srvResponse" structure. The receiving C structure code is as depicted below:

#define  MAXDATA 128
#define  DATALEN 64
#define  MSGLEN 128

#pragma pack(push,1)

typedef struct _srv_RespAlarm{
     short id;
     short level;
    char description[MSGLEN];
} _srv_RespAlarm;

typedef struct _srv_DataPkt{
     short numpkt;
     char prmname[MAXDATA][DATALEN];
     char prmvalue[MAXDATA][DATALEN];
} _srv_DataPkt;

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;
 
typedef struct srvResponse{
     short code;
     short event;
    char message[MSGLEN];
    _srv_RespAlarm alarm;
    _srv_DataPkt data;
    _srv_BasicFlds cmdelem;
 } srvResponse;


I tried with the attached LabVIEW code, but it doesn't work. Any suggestions?

0 Kudos
Message 1 of 14
(4,128 Views)

Add string indicator on FP in hex mode.
Also check, what you get in C-program. You can compare two strings and find mistake.

0 Kudos
Message 2 of 14
(4,106 Views)

You really need more information about how the C code will deserialize the incoming data. Your use of a LabVIEW array for the 2D array won't work, because LabVIEW will prepend the array length. You need to find out how the C code will turn the incoming string into a 2D array, and match that.

0 Kudos
Message 3 of 14
(4,104 Views)

In the C code, they simply read the socket and assign it to the C structure. The individual structure elements stores the values assigned to them and can be accessed thereafter in the program.

 

It is a platform specific issue, how LabVIEW is packing it. So I need to know, If I am doing some mistake in packing it and sending over the network.

 

 

0 Kudos
Message 4 of 14
(4,073 Views)

You are certainly doing some mistake. Those arrays in the structures are all fixed size and therefore inlined (they couldn't be handled as a flat data structure otherwise to be directly streamed over the network). Even if they were string pointers that would be not the same than a LabVIEW string.

 

But to emulate embedded fixed size arrays in LabVIEW you normally would create clusters of the specific amount of elements and plase them inside the outer cluster. Only LabVIEW does not support clusters with more than 512 elements in them (and handling even 128 elements clusters is already a pain in the ass here). So you will have to calculate the size of the buffer by hand and allocate an according array of uInt8. Then copy the various elements into the array at the right offset. Also note that the strings in there will need a zero byte appended explicitedly by you. LabVIEW does not terminate its strings with a zero byte but always knows the exact length of the string as an internal attribute of the string.

 

Basically

 

typedef struct _srv_RespAlarm{
     short id;
     short level;
    char description[MSGLEN];
} _srv_RespAlarm;

 

can be represented as a cluster with 2 int16 followed by a cluster with 128 uInt8.

 

But:

 

ypedef struct _srv_DataPkt{
     short numpkt;
     char prmname[MAXDATA][DATALEN];
     char prmvalue[MAXDATA][DATALEN];
} _srv_DataPkt;

 

would be a cluster with 1 int16 followed by two clusters with 128 * 64 uInt8 each, but as explained above you can't really create such clusters in LabVIEW.

Rolf Kalbermatter
My Blog
0 Kudos
Message 5 of 14
(4,068 Views)

Thank you for the reply.

 

I guess, I couldn't follow your instructions correctly (else the attached code could have worked :))- thouh, tried modifying the stufff attached.

 

 

Download All
0 Kudos
Message 6 of 14
(4,043 Views)

Several things seem wrong here.

 

_srv_RespAlarm contains first two shorts, which are i16 not i8 numbers, same about many other places. 

seq is of type int which is an i32 not an i16 unless your source code comes from Windows 3.1 times.

The parameter arrays need to contain exactly 128 times 64 bytes each, not the number of packets you enter through the control, which can be and often will be a lot less.

num packet would be the number of data packets that should be send and could be implicitedly gotten from the Parameter Names and Parameter Values arrays.

Rolf Kalbermatter
My Blog
0 Kudos
Message 7 of 14
(4,032 Views)

Thank you again rolfk.

After making the data type changes in LabVIEW, the C code was able to receive the "Message" and "Alarm Message" contents correctly. First two shorts of _srv_RespAlarm are getting captured in C code but their values are (2816, 3072) which I never sent through LabVIEW in any of the fields. Rest all fields are empty mostly (except version, sequence, priority fields- these shows value as 0)

0 Kudos
Message 8 of 14
(4,013 Views)

I changed the endian to - "native, host order" and excluded the "_srv_DataPkt" structure/ cluster. Modified the C program to receive these fields only. C program receives every thing correctly.

 

Now the real issue is how do I deal with the "_srv_DataPkt" structure/ cluster. The cluster of clusters (names and Values) is not working properly. Presently, I am ensuring that the names and values arrays will have 128 element, though at the end will have to ensure that the for loop runs there for 128 times strictly.

 

Can't figure out what's going wrong.....Any suggestions.....

 

Main_Vi.PNG

 

 

Subvi_Code.PNG

 

 

 

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

Several things are wrong here!

 

First you better apply a fixed 128 constant to the N terminal of the two loops and disable autoindexing for the string arrays and add an explicit index array inside the loop.

Then you have a cluster of 64 LabVIEW strings instead of a cluster of 2 * 128 clusters of 64 U8 elements. When LabVIEW flattens that it does something very different than what you do want.

 

Also since your client program is written in C on an x86 architecture it would be better to set the endianess explicitedly to little endian. As it is if you ever try to run this code on a big endian system (yes the PPC based cRIO systems are still big endian and fully supported in the latest version) then native will use that and mess up your data.

Rolf Kalbermatter
My Blog
0 Kudos
Message 10 of 14
(3,992 Views)