LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How does the "Flatten to string" function actually work?

I am setting up a C# app to communicate with an existing machine that runs on NI hardware and was programmed via LabView. The old GUI tool I want to replace (also made via LabView) controls the machine by sending commands via TCP.

I sniffed the TCP packets with wireshark before realizing I can check the actual "code" for the current app. The outgoing commands are flattened twice. Once via the "variant to flattened string" and again via "flatten to string" functions. Does anyone know how these flatten operations actually work so that I can write my own functions in C# to send commands to the machine? Changing the interpreting code on the machine unfortunately is not an option so I really need to recreate the flattened strings in my C# app.

As an example a string like ":{14,401E+0, 10.901E+0, Abs}>" gets turned into "@,ÍOß;dZ@%ÍOß;dZ " in the debugging view in LabView (I put probes before and after the flatten function and got this as outputs). I also can't find a recipe in the doc: https://zone.ni.com/reference/en-XX/help/371361R-01/glang/flatten_to_string/

0 Kudos
Message 1 of 45
(6,456 Views)

Hi Tester,

 

what exactly is your problem?

When I flatten your string I get a different output:

check.png

(The string length is prepended with 4 bytes.)

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
0 Kudos
Message 2 of 45
(6,434 Views)

The example is the "variant to flattened string"

Capture (1).JPGCapture.JPG

0 Kudos
Message 3 of 45
(6,427 Views)

Hi Tester,

 

what exactly are you talking about?

check.png

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
0 Kudos
Message 4 of 45
(6,417 Views)

I posted screenshots - the probes are put before and after the flatten block. Not sure what's going on here - I am not a LabView Programmer and am just trying to understand the flatten functions as I see them in this code that was given to me.

Thanks for your effort so far - I hope we can figure this out.

EDIT: Oh i see this is not a string but the format is actually <Variant:{....}>

0 Kudos
Message 5 of 45
(6,412 Views)

Hi Tester,

 

I still cannot reproduce your problem:

check.png

Can you replicated my litte snippets and post the results?

 

EDIT: Oh i see this is not a string but the format is actually <Variant:{....}>

Very often you will read comments like this:

When there is a problem with your VI then you should attach your VI! We cannot debug images with LabVIEW!

Providing an example VI to demonstrate the problem is usually the first step to get help!

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
0 Kudos
Message 6 of 45
(6,406 Views)

I would if I could - as I said I am not a LabView programmer and have no idea how to do a minimal example for my case. Also I am not allowed to send the full vi because of the IP (this is a file from work that I am not allowed to just send out). I know I want help from you so should provide you with everything that you need but my hands are tied here 😞

0 Kudos
Message 7 of 45
(6,390 Views)

Gerd, the probe on the Variant does of course not display the garbled binary string but the proper content inside the Variant. The LabVIEW Variant display is smart enough to deal with that.

 

To the OP, it is unfortunate that there is actually a double encoding in this app. The normal flatten format is well documented and understood (although not trivial at all to decode in something like C#, but that is the problem with any serialization/deseriliation format). The internal Variant format however is a different beast and nowhere documented and to make matters worse it will also depend on the used LabVIEW version. NI specifically reserved the right to modify this format at will by not documenting the binary format of it. The LabVIEW Byte String to Variant funtion is smart enough to observe the embedded version number and adapt accordingly but there is no external library to my knowledge that can do the same and no documentation about the different versions either. There even is a little known gem somewhere in vi.lib that is a special version of the Variant to Byte String function and allows to actually set the desired version of the flattened stream data.

 

If the input data to Variant to Byte String would be always a string then it would be manageable but why would someone even bother to flatten (serialize) something like that at all? And then even twice?

 

The second Flatten is in this context almost a NOP. It simply prepends the 32 bit integer with the number of bytes contained in the flattened variant stream, supposedly so the remote side can easily extract a message from the wire by first reading 4 bytes and converting that to a 32 bit integer and then reading as many bytes to pass to the Byte String to Variant function. Then it will likely use the Variant inspection functions to do some sort of reflection like operation to get back at the data.

Rolf Kalbermatter
My Blog
0 Kudos
Message 8 of 45
(6,383 Views)

So you are saying that NI has some proprietary code for something as "basic" as a flatten operation that they are not willing to make public? that is ****** up - how do you guys deal with a programming language that does this? (sorry I am just frustrated with this problem :()

0 Kudos
Message 9 of 45
(6,380 Views)

Well the Variant format is highly dynamic. The problem here is not so much that that even exists and is not documented but that someone who wrote that application decided to use this format to do interapplication communication. That is still fine as long as you know you will stay in LabVIEW on both sides but it is certainly a choice made.

When dealing with sending data over a wire I of course will evaluate first if there is even a remote chance that sometimes down the line someone somehow might want to interface to that from something else than LabVIEW and if that is the case then of course you would not use the Variant format on such a link.

That said even if he hadn't used the Variant to Byte String function but simply the Flatten to Byte String one you would be in for a hard ride despite that that is basically fully documented (well almost as it could contain Waveforms and other special data types that can contain Variants too). I've written my share of code both in LabVIEW and outside of LabVIEW in C, Java and Lua to deal with the flattened format and its highly recursive nature is a sure way to get your brain cells into knots after a short while.

Personally if there is a chance that data needs to be shared on the wire with non-LabVIEW clients I would definitely propose to use something like Json or XML format which are supported too.

If concise data streams are wanted I usually resorted to my own binary data protocol with some header structure that indicates protocol version, protocol element type and such and then the actual data put on the wire exactly like I wanted.

 

I"m not saying that the actual binary format couldn't be deduced. The variant in essence flattens both the actual type descriptor and the contained flattened data into a single stream. The LabVIEW type descriptor is actually documented in that document you pointed out as is the flattened data format. It's just how these two are exactly put in the overal structure and the fact that everything is made even more complicated by the fact that LabVIEW Variants can have so called attributes which are basically key-value dictonaries with the key being a string and the value being a Variant again and which have to be flattened too. I never have felt inclined enough to really spend any time on this though and I don't find it necessary either.

Rolf Kalbermatter
My Blog
Message 10 of 45
(6,366 Views)