Data format for binary data transfer

binarydata

I have to make an oscilloscope. Ideally, the oscilloscope connects to a probe. This probe should be another program, and could get the data locally or from a network. This data are numbers, floats and/or integers. The number of channels may vary. And they change with time. Not all channels need to have the same frequency.

Now, sometimes the frequency can be 1KHz, so using json is not ok because is wastes a lot of resources since is based in text. I'm looking for a binary data format, so the data transfer is faster.

So the first part of the question is: Do you know of a format to transfer binary data like this? It should have some kind of header, and then just numbers. My guess is that somebody must have had this problem before and there should be some kind of library to use this.

Then comes the second part of the question: What protocol should we use to transfer the data?

Maybe using json but with a base 64 encoder for the data using standart http calls could work, but for 1KHz signal that doesn't make sense. I wonder what people do to solve this.

Best Answer

You might also want to consider looking up the subject of "ber tlv"

http://en.wikipedia.org/wiki/Type-length-value

This is the data stream format used by the worlds financial processing network, and is the backbone behind Chip & Pin terminals, ATM's and many other banking systems.

The best part about it is it's very simple to use.

The T,L,V part stands for

  • Tag
  • Length
  • Value

The Tag is a numerical identifier that specify's the type of message, in your case if your just making use of the format, you can most likely define your own tags for this, but if you where actually handling real financial data you'd have to use the tag numbers defined in the standard.

The Length part is again simple, it specify's how many bytes of data the value part is, like any value the more bytes you allocate to the length, the longer your payload can be.

The Value part is then just the payload for your actual message, and how you format the bytes for this is entirely up to you.

Beacuse it's such a simple to decode/encode protocol (You can do it entirely using byte arrays) you can easily sent it over UDP using a very small, very fast packet size.

It's also suitable for streaming, and multiple messages can be sent back to back in a continuous non closing connection, which is quite ideal if you decide you must use TCP.

It would in theory work well over HTTP too using a web socket, but I've never actually tried that so I couldn't comment on how well.

As for libraries supporting it, last time I looked "Craig's Utility Library"

https://github.com/JaCraig/Craig-s-Utility-Library

had very good support for TLV based structures in it, as do many of the smartcard libraries that are floating around (TLV is used on a lot of cards too)

If TLV is not your thing, then I'd definately back up what others have said and take a good close look at "Protobuf"

Update

I don't know what language your working in, or even if what I'm about to post will be of any use to you :-) , but here goes anyway.

This is a TLV decoder (Note it has no encoding capabilities, but it should be easy to reverse it) I wrote back in 2008(ish) using C# , it was designed for decoding ber-tlv packets coming off a smart card in a payment terminal, but it might serve as a starting point for you to hack it into a more useful shape.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Card_Analyzer
{
  public class tlv
  {
    public int tag = 0;
    public int length = 0;
    public byte tagClass = 0;
    public byte constructed = 0;
    public List<byte> data = new List<byte>();
  }

  public class tlvparser
  {
    // List of found TLV structures
    public List<tlv> tlvList = new List<tlv>();

    // Constructor
    public tlvparser(byte[] data)
    {
      if (data != null)
      {
        this.doParse(data);
      }
    }

    // Main parsing function
    public void  doParse(byte[] data)
    {
      int fulltag = 0;
      int tlvlen = 0;
      int dptr = 0;

      while (dptr < data.Length)
      {
        byte temp = data[dptr];
        int iclass = temp & 0xC0;
        int dobj = temp & 0x20;
        int tag = temp & 0x1F;

        if (tag >= 31) // Using extracted vars, decide if tag is a 2 byte tag
        {
          fulltag = (temp << 8) + data[dptr + 1];
          tlvlen = data[dptr + 2];
          dptr += 3;
        }
        else
        {
          fulltag = temp;
          tlvlen = data[dptr + 1];
          dptr += 2;
        }// End if tag 16 bit

        if ((tlvlen & 128) == 128)
        {
          tlvlen = (tlvlen << 8) + data[dptr];
          dptr++;
        }

        tlv myTlv = new tlv();
        myTlv.tag = fulltag;
        myTlv.length = tlvlen;
        myTlv.tagClass = Convert.ToByte(iclass >> 6);
        myTlv.constructed = Convert.ToByte(dobj >> 5);

        for (int i = 0; i < tlvlen; i++)
        {
          if(dptr < data.Length)
            myTlv.data.Add(data[dptr++]);
        }

        if (myTlv.constructed == 1)
          this.doParse(myTlv.data.ToArray());

        tlvList.Add(myTlv);

      }// End main while loop
    }// End constructor
  }// end class tlvparser
}// end namespace

If it's of no use, then feel free to just ignore it.

Related Topic