08-15-2017 11:04 AM
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);
...
Solved! Go to Solution.
08-15-2017 11:07 AM
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?
08-15-2017 11:19 AM
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, ...]
08-15-2017 11:21 AM
To make our lives easier, can you attach a simple VI that contains a typical received string as diagram constant?
08-15-2017 12:16 PM
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.
08-15-2017 01:23 PM
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.
08-15-2017 01:35 PM
Or, much simpler, make the array into a cluster as I suggested:
08-15-2017 03:33 PM - edited 08-15-2017 03:34 PM
08-15-2017 03:39 PM
@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.
08-16-2017 09:12 AM
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.