You are here :

You can use this API to send a track recored with LeonardoLive compatible programs to
a LeonardoXC server.

There are 2 options:

# Send the track that is stored at the server, so no re-uploading is done, but this means that the tracking interval be may too big or that there are missing trackpoints due to bad mobile signal. This method is reffered to as 'live-partial-submit'

# Re-upload the trackpoints that the program has stored internally into the phone, it may be even at 1 sec interval! This is the recommended method and it is called 'full-reupload'. This method uses a) differential format so that only changes between points are written AND b) a 'deflate' compression on the resulting output. This makes a very efficient compression of rates up to 90%

A tracklog of 2 sec interval and duration of 1 hour consists of 1800 trackpoints, it will convert in differential format at 7200 bytes and deflated around 55% will result in 3960 bytes or 3,8 Kb


!!!URL to POST

www.livetrack24.com/client.php

or for testing

test.livetrack24.com/client.php

NOTE : the test url is for submitting tracks recorded on the test server by using the 'live-partial-submit' option.

!!!POST VARIABLES

__Variables needed in all methods__

__Variable name__ __Values__
op => submit

sessionID => The sessionID of the tracklog
liveUsername => The username of on livetrack24.com
liveUserID => The userID IF the user has loggedin, else use 0
gliderType => put the NUMERIC value from the table below
1=>"Paraglider"
2=>"Flex wing FAI1"
4=>"Rigid wing FAI5"
8=>"Glider"
16=>"Paramotor"
32=>"Trike"
64=>"Powered flight"
128=>"Hot Air Balloon"
16385=>"Walk"
16386=>"Run"
16388=>"Bike"

gliderName => Name of the vehicle/glider ie "Gradient Golden 2 26"
platform => Nokia 2600c // the phone model as it is acquired from a system call
gps => the GPS name , use the string "Internal GPS" for phones with integrated GPS
programName => fixed value use only alphanumerics no spaces, first Letter of words in capitals
programVersion => version of your program you can use free text like 1.4.5
comments => user provided comments aboub the flight
url => a user provided URL that may contain further info about the flight

leonardoServer => the numeric ID of the target leonardo server, here is the list up today
1=>www.paraglidingforum.com
2=>www.sky.gr
3=>www.xcportugal.com
4=>www.xcbrasil.org
5=>xc.DHV.de
7=>www.foroparapente.co
so for example use 1 for sending to paraglidingforum.com

username => leonardoXC username
password => leonardoXC password


__Variables for 'live-partial-submit'__
format => ALREADY_UPLOADED_DATA


__Variables for 'full-reupload'__
format => FORMAT_BINARY_COMPRESSED
compressed => 1 for 'deflated' , 0 for just the differential format
trackID => If the track was live and the program had a means to
grab the trackID of on the server then give it here. Or just put 0,
firstTM => the Timestamp (sec till unix epoch 1-1-1970 GMT) of the first point.


!!Prepare the compressed file

INIT VARIABLES
tm0=0;
latitude0=0;
longitude0=0;
alt0=0;

FOR EACH TRACKPOINT DO
if (tm0==0) {
// we output the full record , this is the first TRACKPOINT
CALL fullRecordBinary()
} else {
// see if we can use differential format:
/*
1 Full or diff format
3 time diff 8 secs
7 alt diff 6 bits-> 64 m + 1 bit sign
11 lat diff 10 bits + 1 sign (1024)
10 lon diff 9 bits + 1 sign (512)
total 1+3+7+11+10 = 32 bits = 4 bytes
*/
int d_tm=tm-tm0;
int d_alt=alt-alt0;
int d_lat=latitude-latitude0;
int d_lon=longitude - longitude0;
if ( d_tm < 8 && Math.abs(d_alt) < 64 &&
Math.abs(d_lat) < 1024 && Math.abs(d_lon) < 512 ) {

byte[] outBytes =new byte[4];

// 12345678 12345678 12345678 12345678
// FtttAaaa aaaOoooo oooooLll llllllll

outBytes[0]=outBytes[1]=outBytes[2]=outBytes[3]=0;

outBytes[0]= (byte)0x80; // differential format
outBytes[0] |= (byte)( (d_tm << 4) & 0x70 ) ;
if (d_alt<0) outBytes[0] |= 0x08; // negative d_alt
outBytes[0] |= (byte)( (Math.abs(d_alt) >>3 ) & 0x07 ) ;


outBytes[1] |= (byte)( (Math.abs(d_alt) <<5 ) & 0xE0 ) ;
if (d_lon<0) outBytes[1] |= 0x10; // negative d_lon
outBytes[1] |= (byte)( (Math.abs(d_lon) >> 5) & 0x0F ) ;

outBytes[2] |= (byte)( (Math.abs(d_lon) << 3) & 0xF8 ) ;
if (d_lat<0) outBytes[2] |= 0x04; // negative d_lat
outBytes[2] |= (byte)( (Math.abs(d_lat) >> 8) & 0x03 ) ;

outBytes[3] |= (byte)( (Math.abs(d_lat) ) & 0xFF ) ;

out.write(outBytes);
} else { // revert to full
// we output the full record
CALL fullRecordBinary()
}

}

tm0=tm;
latitude0=latitude;
longitude0=longitude;
alt0=alt;

GO ON WITH THE NEXT TRACKPOINT...



!!FullRecord2Binary()

final static private int DEGREESTOINT = 46603;

public static byte[] fullRecordBinary(int tm,Float lon,Float lat,short alt) {

res_arr2[0]=toByta(tm);

res_arr2[1]=new byte[3];
res_arr2[2]=new byte[3];

int longitude = lon * DEGREESTOINT ;
res_arr2[1][0] = (byte)(0xff & (longitude >> 16));
res_arr2[1][1] = (byte)(0xff & (longitude >> 8));
res_arr2[1][2] = (byte)(0xff & longitude);

int latitude = lat * DEGREESTOINT
res_arr2[2][0] = (byte)(0xff & (latitude >> 16));
res_arr2[2][1] = (byte)(0xff & (latitude >> 8));
res_arr2[2][2] = (byte)(0xff & latitude);


res_arr2[3]=toByta(alt);

byte[] res=concat(res_arr2);
return res;
}

public static byte[] toByta(int data) {
return new byte[] {
(byte)((data >> 24) & 0xff),
(byte)((data >> 16) & 0xff),
(byte)((data >> 8) & 0xff),
(byte)((data >> 0) & 0xff),
};
}


public static byte[] toByta(short data) {
return new byte[] {
(byte)((data >> 8) & 0xff),
(byte)((data >> 0) & 0xff),
};
}