Compressed VRS Feed Format
The compressed feed carries BaseStation (port 30003) format messages. Only TRANSMISSION messages can be compressed, and then only if they have an ICAO code present on them and they are not ALL-CALL-REPLY messages.
The format uses a mix of big-endian and little-endian values. Most of the values are little-endian but 3-byte integers and ICAOs are stored big-endian.
Each message is encoded into a variable number of bytes. The encoded message always begins with a fixed-length header block:
|0||1||Length of the entire message including this header.|
|1||2||Checksum, see note 1.|
|3||1||The transmission type, see note 2.|
|4||3||The ICAO, high-byte first (e.g. an ICAO of AABBCC is written as AA BB CC).|
|7||2||Field flags, see note 3.|
Note 1 - Checksum
The checksum is a CRC-16 checksum with a polynominal of 0xA001. When calculating the CRC start with an initial value of 0. The checksum is calculated over the entire message including the length. When calculating the checksum fill bytes 1 and 2 of the header with zero (i.e. assume a checksum of 0 when feeding the message into the checksum).
The checksum is written low-byte first, e.g. a checksum of 0xABCD is written as CD AB.
Note 2 - Transmission Types
Transmission types are encoded as follows:
|Transmission Type||Byte Value|
|Identification and Category||0x01|
|Air to Air||0x07|
Note 3 - Field Flags
These are a set of bitflags that indicate which fields are present in the message body and the order in which they have been written.
|Track||0x0008||Track * 10.0, Float/Short|
|Squawk has changed||0x0100||Compressed Flags|
|Ident active||0x0400||Compressed Flags|
|On ground||0x0800||Compressed Flags|
Note that tracks are multiplied by 10 and then written as an integer - e.g. a track of 10.17 is written as an integer of 101.
The flag bytes are written low-byte first, e.g. a flags value of 0x0fff would be written as FF 0F.
The message body consists of every field indicated by the Field bitflags in the header in ascending order of bitflag value. So for example, if the original message had a squawk and a callsign then the Field bitflags value would be 0x0081 and the body would consist of the Callsign value first (because it has a bitflag value of 0x01) followed by the Squawk (because it has a bitflag value of 0x80).
If any of the Compressed Flags are present then they are packed together into a single byte after all of the other fields. If they are not present then they occupy no room in the body, the single byte that would contain them is not written.
Strings are written as one byte of length followed by the string in ASCII format. Strings longer than 255 bytes are not supported.
Float/Ints are converted to an integer and normalised to a value of +8388607 / -8388607 (0x7fffff). If the value is negative then the value is made positive and bit 0x800000 is set. The value is then written as a three byte integer, high-byte first (e.g. a value of 0x112233 would be written as 11 22 33).
To decode a Float/Int read the three bytes into store and test bit 0x800000. If it is set then AND the value with 0x7fffff and make the result negative.
Float/Shorts are converted to an integer and normalised to a value of +32767 / -32768. They are then written to the stream low-byte first, e.g. a value of 0xAABB would be written as BB AA.
Floats are written as 4 byte IEEE single-precision floating point number with the low-byte written first, e.g. a value of 0xAABBCCDD would be written as DD CC BB AA.
Shorts are written as a 2 byte integer, low-byte first. E.G. a value of 0x1122 would be written as 22 11.
When the squawk is written it is treated as a decimal value. For example, a squawk of octal 7654 would be written as the decimal value 7654 (0x1de6, or E6 1D on the feed), not 4012.
Compressed Flags Format
Every compressed flag is written as a bit within the same byte. If no compressed flag format fields are present in the header's Field bitflags then the compressed flag byte is not written to the body. The bits occupied by field of the compressed flag fields is as follows:
|Squawk has changed||0x01|
Copy bytes 1 and 2 from the message and then set them to zero. Calculate the checksum of the message and compare against the bytes you saved. If the checksum compares correctly then the message is valid and can be decoded, otherwise you should discard it.
You will note that the session ID, aircraft ID, flight ID, message generated time and message logged time fields from the original BaseStation message are not sent in the compressed feed. Most applications that use a BaseStation feed do not use any of these fields. You can usually set them to zero or miss them out of the reconstructed BaseStation message. Virtual Radar Server sets the message generated time to the time that the message was decoded from the feed.
When reconstructing the Track field remember to divide the value by 10 before use. Also remember that the squawk is a decimal number on the feed, not an octal number.