LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 
Reply

How to efficiently read network data into struct and correct endianess

Solved!
Go to solution

I have a device that transmits the following data over TCP

struct SomeData
{
  uint32_t counter;
  uint32_t status;
  double values[20];
} __attribute__((packed));

I can successfully read and make use of this data from a LabVIEW client, but the process is cumbersome.  Currently, I am manually selecting sub-arrays of bytes, reversing them to correct the endianess, type casting them to the correct type, and then bundling them into a struct.  Is there a more efficient way to do this?  I have explored using flatten/unflatten from string but I end up with Error 116.  Basically, what I want is something like the following C code.

SomeData some_data;
recv(sock_fd, &some_data, sizeof(some_data), MSG_WAITALL);
some_data.counter = be32toh(some_data.counter);
...

 

0 Kudos
Message 1 of 16
(892 Views)

what does the TCP string look like when LabVIEW receives it? Do you get the whole message in one packet or are there multiple reads involved?

0 Kudos
Message 2 of 16
(891 Views)

I get the whole message.  An example is 

[15, 0, 0, 0, 1, 0, 0, 0, 61, 10, 215, 163, 112, 157, 64, 64, ... ]

which should correspond to 

counter = 15

status = 1

values = [33.23, ...]

 

0 Kudos
Message 3 of 16
(881 Views)

To make our lives easier, can you attach a simple VI that contains a typical received string as diagram constant?


LabVIEW Champion Do more with less code and in less time
0 Kudos
Message 4 of 16
(879 Views)

Unflatten from String should do what you want. You need a LabVIEW cluster that matches the struct. The array element of the struct should be a 20-element cluster in LabVIEW (create an empty array of the appropriate data type, wire it to "Array to Cluster," set cluster size to 20, create a control, put it into your overall cluster).

 

Use that new cluster as the type input to Unflatten from String. Wire the string from TCP Read into Unflatten from String. Set the endianness input, if necessary. In some cases you can use Type Cast instead of Unflatten from String, but then you don't get to pick endianness.

0 Kudos
Message 5 of 16
(854 Views)

That array will mess things up a little.  But things are arranged in such a way that we can easily get around it.  I would use three Unflatten From Strings.  We can abuse the "Remaining String" output of the Unflatten From String and wire it up to the next.  This will allow us to get parts at a time.  The first gets the U32 counter.  The second the U32 status.  For the last one, you use an array of doubles as the data type and be sure to wire a FALSE to the "data includes array or string size".  You can then bundle the three data points together into your cluster.


There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
0 Kudos
Message 6 of 16
(840 Views)
Solution
Accepted by topic author tysonl
08-16-2017 07:54 AM

Or, much simpler, make the array into a cluster as I suggested:

unflatten struct.png

0 Kudos
Message 7 of 16
(829 Views)

@nathand wrote:

Or, much simpler, make the array into a cluster as I suggested:

unflatten struct.png


That is right but the data is obviously in Little Endian format from the example data he posted!

 

Little Endian = Little End first = LSB first

Rolf Kalbermatter
Averna BV
LabVIEW ArchitectLabVIEW ChampionLabVIEW Instructor
Message 8 of 16
(811 Views)

@rolfk wrote:

That is right but the data is obviously in Little Endian format from the example data he posted!


Good point! I was focused on the array/cluster issue and didn't actually look at the data, I put the constant there to show that the input for endianness exists.

0 Kudos
Message 9 of 16
(806 Views)

I have tried using Unflatten From String, but I constantly get error 116 (Unflatten or byte stream read operation failed due to corrupt, unexpected, or truncated data).  If I clear the errors after the Unflatten From String, then the counter and status come out correct, but values is empty.  The simple code I am using is the following. Note, I have modified my device and my code to have values of length 3, not 20, in order to make it simpler to see all the data.tcp_client_some_data.png

 

 

 

 

0 Kudos
Message 10 of 16
(764 Views)