Technical Reference - Real-time Telemetry
With Tacview Advanced and above, you can stream telemetry data in real-time using the public protocol described in this documentation. Handy to oversee, in real-time, a battle taking place in a flight simulator, this feature will be extended later to real-life so you can watch a flight currently in progress using smartphones and/or low cost data recorders.
Like the acmi format 2.x, Tacview real-time telemetry protocol been developed to be very easy to use. It is a pure UTF-8 text protocol which can be implemented with most languages, including scripts like LUA. After a very simple handshake (connection) with Tacview, the data flow will be steady, relatively compact and robust thanks to TCP/IP.
Real-time Telemetry Protocol 101
Simply put, the real-time telemetry protocol is using a TCP/IP socket to transmit sequential uncompressed ACMI 2.x data.
The third-party application is the host of the session and Tacview is a client. In other words: the third-party application will host a session waiting for one or more Tacview clients to join it to review the data in real-time. For example, you can connect many remote and local Tacview clients at the same time to the exporters written for DCS World, FSX and X-Plane.
The first part of the communication is called handshaking. This is an exchange of data used to make sure that both the host and Tacview are talking the same language. The handshake also contains the user name for each party as well as the password hash required to join a protected session. The username can contain any UTF-8 character except control characters like \n.
If any party is not happy with the handshake data, it can simple close the connection with a clean socket shutdown.
As soon as both parties agree about the protocol and the host has accepted the password hash provided by Tacview, the effective telemetry transition can start.
Here is an example of the data exchanged between the host and one client:
Handshake data sent by the Host (third-party application)
XtraLib.Stream.0␊ Tacview.RealTimeTelemetry.0␊ Vyrtuoz␊ ␀
As soon as the socket connection is established, the host sends the low-level protocol name and version XtraLib.Stream.0 followed by Tacview high-level protocol and version Tacview.RealTimeTelemetry.0. The next data is the host username Vyrtuoz which is used only for information purpose, to display the host name on the client computer. The last line sent by the host is empty because the host does not send the session password hash to the clients for obvious reasons.
Each line, but the last one, ends by a single \n line-feed character and the handshake data packet ends by a terminal \0. Tacview exporters or client will cleanly drop the connection if the handshake takes too much time to complete.
Handshake data sent by the Client (Tacview)
XtraLib.Stream.0␊ Tacview.RealTimeTelemetry.0␊ Frantz RAIA␊ 0␀
As soon as the connection is established, the client sends its handshake data to the host. It contains the same data: low-level protocol id, high-level protocol id, and client name. However, the last entry now contains the hexadecimal value of the password hash required to establish a connection to a protected session.
If no password is required to join the session, the password hash will be ignored by the host and the connection established (if the protocols match). If a password is required, the host will compare the provided hash with the required one and will cleanly close the socket in case of mismatch.
The password hash is a simple CRC-64-ECMA. A more robust hash may be implemented in a future revision if necessary.
The host nor the client do explicitly inform the other peer of the reason of a rejection. They are free to cleanly close the socket at any time. The client can know if the password has been rejected if the rest of the handshake data was matching the protocol parameters provided by the host.
As soon as the host has approved the connection, it may start sending data to the client. There is no keep-alive packet or explicit request from the client. The data will automatically flow as required.
Incoming data from the host (header)
You should recognize here Tacview acmi format 2.x. The data transmitted is identical to the uncompressed data saved in an acmi file.
Incoming data from the host (metadata)
0,ReferenceTime=2017-05-01T05:27:00Z 0,RecordingTime=2017-03-09T16:17:49Z 0,Title=test simple aircraft 0,DataRecorder=DCS2ACMI 1.6.0 0,DataSource=DCS 188.8.131.528 0,Author=Vyrtuoz 0,ReferenceLongitude=37 0,ReferenceLatitude=37 40000001,T=4.6789343|5.1865487|2000|617414|-291014,Type=Navaid+Bullseye,Color=Blue,Coalition=Enemies 40000002,T=1.987465|8.0833075|2000|371700|11557,Type=Navaid+Bullseye,Color=Red,Coalition=Allies
To reduce lag, the host should flush a new "packet" of data every time a frame is complete. That way, Tacview will be able to playback the data as soon as it is produced or recorded.
Incoming Data (samples)
#114.76 0,Category=CAP 101,T=4.8502002|4.9274637|20.26||-0.2|75.9|634576.06|-318348.25|69.9,Type=Air+FixedWing,Name=Su-27,Pilot=Vyrtuoz,Color=Red,Coalition=Allies,Country=ru,Debug=wsType[184.108.40.206],Importance=1,IAS=0,Throttle=0.72,Afterburner=0,AirBrakes=0,Flaps=1,LandingGear=1,Tailhook=0,HDM=63.28
Tacview dynamically checks the performance of the data transmission to smoothly adjust its time counter to playback the last received sample a bit after the next sample should be received.
Incoming Data (samples)
There is currently no time-out during data transmission: Tacview will not drop the connection if the host temporarily pause the transmission for any reason.
Data Size Optimization
Use the proper end-of-line character
Use \n as the end-of-line character instead of \r\n. This will save one byte per line. Which can result in quite a lot of savings over time.
Avoid redundant data
Output new samples only when the corresponding data has changed. Tacview will smartly interpolate values.
Use longitude and latitude offsets when applicable
If your data is limited to a 10 x 10 degree of longitude/latitude sector, consider using ReferenceLongitude and ReferenceLatitude to reduce your coordinates size.
Tweak your samples resolution
Output only the relevant digits. Unnecessary trailing digits will just make the data stream bigger without providing any meaningful data. You may also want to write your own printf() function which does not output useless trailing zeros. This will also save a lot of bandwidth.
You should consider exporting your data with the following resolution. This will help to save bandwidth and storage space:
|# (frame time)||0.01 second
(Tacview truncate samples time to 0.01 second for technical reasons anyway)
|T (longitude/latitude)||0.0000001 degree
(gives 0.011 meter resolution at the equator)
|T (altitude)||0.01 meter|
|T (roll/pitch/yaw)||0.1 degree|
|T (flat coordinates)||0.01 meter|
Tweak the export frequency by sample type
Perhaps the biggest optimization you can do, is to tweak your export frequencies depending on the type of object. The following export frequencies give a good balance between size and latency. They are used for the DCS World exporter. You should not export data more often than suggested in this array. You may lower the frequency further if your objects are always following smooth trajectories.
|Player(s) aircraft||10 Hz (and up to 16 Hz when remotely controlled by Tacview)|
|Weapon||8 Hz (for high roll objects like missiles and rockets)|
|Air||5 Hz (for air objects in general)|
|2 Hz (object with smooth ballistic trajectories)|
|All other objects||1 Hz|