COAA planeplotter protocol description

RPi-based uploader to PlanePlotter protocol description

This is a draft. It is known to be incomplet and incorrekt, with bad formatting.

Communication on port 9742/UDP. List of possible request message headers: "TRSEND ", "TRSeND ", "WhoAmI" (we respond with "IAm %d.%d.%d.%d" string where %d.%d.%d.%d is an IP of incoming connection).



Request:
0000   54 52 53 65 4e 44 20 31 34 39 36 38 30 35 31 31  TRSeND 149680511
0010   32 20 31 30 20 31 38 38 2e 36 34 2e 31 39 31 2e  2 10 188.64.191.
0020   33 35                                            35

Description:
TRSeND (unixtimestamp) (time offset) (source ip)

Response:
0000   56 57 ×× ×× ×× ×× ×× ×× ×× ×× ×× ×× ×× ×× ×× ××  VW××××××××××××××
0010   ×× ×× 47 46 46 4e 43 47 45 49 40 40 40 40 40 40  ××GFFNCGEI@@@@@@
0020   40 40 40 46 4a 40 4c 41 40 47 4f 4d 4b 46 4b 43  @@@FJ@LA@GOMKFKC
0030   4c 41 45 4d 40 46 4a 40 4c 41 47 44 43 4b 43 4c  LAEM@FJ@LAGDCKCL
0040   40 43 40 40 40 40 40 40 40 40 40 40 40 40 40 40  @C@@@@@@@@@@@@@@
0050   40 40 20 20                                      @@  

0000   56 57 ×× ×× ×× ×× ×× ×× ×× ×× ×× ×× ×× ×× ×× ××  VW××××××××××××××
0010   ×× ×× 4f 49 46 4e 43 47 45 49 40 40 40 40 40 40  ××OIFNCGEI@@@@@@
0020   40 40 44 44 40 48 42 48 40 41 49 49 40 4a 4c 4d  @@DD@HBH@AII@JLM
0030   4d 40 48 4d 44 44 40 48 42 48 45 48 4b 49 48 44  M@HMDD@HBHEHKIHD
0040   4d 4b 40 46 42 43 46 4a 49 46 47 47 48 47 40 43  MK@FBCFJIFGGHG@C
0050   40 40 20 20                                      @@  

0000   56 57 ×× ×× ×× ×× ×× ×× ×× ×× ×× ×× ×× ×× ×× ××  VW××××××××××××××
0010   ×× ×× 4f 4a 46 4e 43 47 45 49 40 40 40 40 40 40  ××OJFNCGEI@@@@@@
0020   40 40 44 4b 4d 41 44 49 40 41 49 4a 41 4a 4b 4e  @@DKMADI@AIJAJKN
0030   4b 4a 48 4d 44 4b 4d 41 44 49 49 40 45 43 43 44  KJHMDKMADII@ECCD
0040   4b 4a 46 40 42 46 45 4c 45 40 4f 4a 48 41 40 43  KJF@BFELE@OJHA@C
0050   40 40 20 20                                      @@  
payload[0]      = 0x56 (86) header; 1 byte
payload[1]      = 0x57 (87) header; 1 byte
payload[2..10)  = user latitude; 8 bytes [enc]
payload[10..18) = user longitude; 8 bytes [enc]
payload[18..34) = aircraft seen on client, unix timestamp; 16 bytes [enc]
payload[34..40) = ICAO; 6 bytes [enc]
paylaod[40..42) = COAA msg type (encoded enum values: 1, 5, 7); 2 bytes [enc]
payload[42..50) = Message mode timestamp blk (see dump1090 source); 8 bytes [enc]

if paylaod[40..42) == 0x4140 (decoded to 1):
  ; aircraft message length 14 bytes
  payload[50..78) = aircraft message; 28 bytes [enc]
  payload[78]     = 0x40 end of message; 1 byte [enc]
  paylaod[79]     = 0x43 end of message; 1 byte [enc]

if paylaod[40..42) == 0x4540 (decoded to 5):
  ; I never seen packet with this message type

if paylaod[40..42) == 0x4740 (decoded to 7):
  ; aircraft message length 7 bytes
  payload[50..64) = aircraft message; 14 bytes [enc]
  payload[64]     = 0x40 end of message; 1 byte [enc]
  paylaod[65]     = 0x43 end of message; 1 byte [enc]

payload[82] = 0x20 (32) end of payload; 1 byte
payload[83] = 0x20 (32) end of payload; 1 byte

Response payload is encrypted by following encoder:

int coaaEncrypt(uint8_t *out, const uint8_t *in, int size)
{
  if (size <= 0)
    {
      return 0;
    }

  const uint8_t *last = &in[size];

  for (; in != last;)
    {
      out[0] = (*in >> 4) + 64;
      out[1] = (*in & 0xF) + 64;
      in++;
      out += 2;
    }

  return 2 * size;
}

Matching decryptor:

int coaaDecrypt(uint8_t *out, const uint8_t *in, int size)
{
  if (size <= 0)
    {
      return 0;
    }

  if (size % 2 != 0)
    {
      return 0;
    }

  const uint8_t *last = &in[size];

  for (; in != last;)
    {
      // out[0] = ((in[0] - 64) << 4) | ((in[1] - 64) & 0xF);
      out[0] = ((in[0] & 0xF) << 4) | (in[1] & 0xF);
      in += 2;
      out++;
    }

  return size / 2;
}
Decoded UDP payloads:
'VW××××××××××××××××GGFNCGEI@@@@@@@@DKMADI@AONFBFBJGHMDKMADII@FMADIOKBCBNHBLKCH@@C@@  '
'67××××××××××××××××776e3759000000004bd14901fe6262a78d4bd149906d149fb232e82cb380030000'
   head (type 'str') 67
   Lat (type 'float') ×
   Lon (type 'float') ×
   seen (type 'long') 1496804983 (59376e77)
   icao (type 'str') 4bd149
   msgtype (type 'str') 01
   msgtimestamp (type 'long') 2808242942 (a76262fe)
   msg (type 'str') 8d4bd149906d149fb232e82cb38003

'VW××××××××××××××××GHFNCGEI@@@@@@@@@FJ@LA@GOODJODNOEM@FJ@LAGDCKBL@C@@@@@@@@@@@@@@@@  '
'67××××××××××××××××786e37590000000006a0c107ff4af4ef5d06a0c1743b2c03000000000000000000'
   head (type 'str') 67
   Lat (type 'float') ×
   Lon (type 'float') ×
   seen (type 'long') 1496804984 (59376e78)
   icao (type 'str') 06a0c1
   msgtype (type 'str') 07
   msgtimestamp (type 'long') 4025764607 (eff44aff)
   msg (type 'str') 5d06a0c1743b2c03

'VW××××××××××××××××GHFNCGEI@@@@@@@@DKMADI@AOOIHAGOGHMDKMADII@FKOABMGLDOMHFJCFGO@C@@  '
'67××××××××××××××××786e3759000000004bd14901ff9817f78d4bd149906bf12d7c4fd86a367f030000'
   head (type 'str') 67
   Lat (type 'float') ×
   Lon (type 'float') ×
   seen (type 'long') 1496804984 (59376e78)
   icao (type 'str') 4bd149
   msgtype (type 'str') 01
   msgtimestamp (type 'long') 4145518847 (f71798ff)
   msg (type 'str') 8d4bd149906bf12d7c4fd86a367f03

'VW××××××××××××××××GHFNCGEI@@@@@@@@DD@HBH@A@@CBJBBBHMDD@HBHEHKIHDOHFJBOK@K@CBEE@C@@  '
'67××××××××××××××××786e375900000000440828010032a2228d44082858b984f86a2fb0b03255030000'
   head (type 'str') 67
   Lat (type 'float') ×
   Lon (type 'float') ×
   seen (type 'long') 1496804984 (59376e78)
   icao (type 'str') 440828
   msgtype (type 'str') 01
   msgtimestamp (type 'long') 581054976 (22a23200)
   msg (type 'str') 8d44082858b984f86a2fb0b0325503

'VW××××××××××××××××GHFNCGEI@@@@@@@@@FJ@LA@G@@MFLICCEM@FJ@LAGDCKCI@C@@@@@@@@@@@@@@@@  '
'67××××××××××××××××786e37590000000006a0c10700d6c9335d06a0c1743b3903000000000000000000'
   head (type 'str') 67
   Lat (type 'float') ×
   Lon (type 'float') ×
   seen (type 'long') 1496804984 (59376e78)
   icao (type 'str') 06a0c1
   msgtype (type 'str') 07
   msgtimestamp (type 'long') 868865536 (33c9d600)
   msg (type 'str') 5d06a0c1743b3903

'VW××××××××××××××××GIFNCGEI@@@@@@@@@FJ@LA@G@@EJFHLOEM@FJ@LAGDCK@G@C@@@@@@@@@@@@@@@@  '
'67××××××××××××××××796e37590000000006a0c107005a68cf5d06a0c1743b0703000000000000000000'
   head (type 'str') 67
   Lat (type 'float') ×
   Lon (type 'float') ×
   seen (type 'long') 1496804985 (59376e79)
   icao (type 'str') 06a0c1
   msgtype (type 'str') 07
   msgtimestamp (type 'long') 3479722496 (cf685a00)
   msg (type 'str') 5d06a0c1743b0703

msgtimestamp field is encoded using following algorithm before encryption:
/*
msgType = msg[0] >> 3;
*/
uint64_t timestamp_mangle(const uint64_t llTimestamp, int msgType)
{
  uint64_t lo = llTimestamp << 2;
  uint64_t hi = llTimestamp >> 30;
  uint64_t mix = (hi << 32) | lo;
  uint64_t sum = llTimestamp + mix;
  uint64_t div = sum / 3;

  if (msgType == 17)
  {
    // BYTE3(v24) = 1; coaa msg type
    int32_t ror = __ROR__(div + 1120, 24);
    return (((div + 1120) << 8) & 0xffffff00) | (ror & 0xff);
  }
  else if (msgType == 11)
  {
    // BYTE3(v24) = 7; coaa msg type
    int32_t ror = __ROR__(div, 24);
    return (((div) << 8) & 0xffffff00) | (ror & 0xff);
  }
  
  return -1;
}

Reg, Auth, Hla, Hlo are credentials from coaa.h file generated by Dump1090 Software Registration Request.

// coaa.h
#define USER_REGNO [int]
#define USER_AUTHCODE [hex string]
#define USER_LATITUDE [float]
#define USER_LONGITUDE [float]

Periodic (once per minute) plane position upload HTTP payload send to www.coaa.co.uk:80:

0000   50 4f 53 54 20 2f 70 6c 61 6e 65 69 6e 66 6f 39  POST /planeinfo9
0010   75 2e 70 68 70 20 48 54 54 50 2f 31 2e 31 0d 0a  u.php HTTP/1.1..
0020   43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 61 70  Content-Type: ap
0030   70 6c 69 63 61 74 69 6f 6e 2f 78 2d 77 77 77 2d  plication/x-www-
0040   66 6f 72 6d 2d 75 72 6c 65 6e 63 6f 64 65 64 0d  form-urlencoded.
0050   0a 55 73 65 72 2d 41 67 65 6e 74 3a 20 50 6c 61  .User-Agent: Pla
0060   6e 65 50 6c 6f 74 74 65 72 0d 0a 48 6f 73 74 3a  nePlotter..Host:
0070   20 77 77 77 2e 63 6f 61 61 2e 63 6f 2e 75 6b 0d   www.coaa.co.uk.
0080   0a 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 3a  .Content-Length:
0090   20 36 37 35 0d 0a 43 61 63 68 65 2d 43 6f 6e 74   675..Cache-Cont
00a0   72 6f 6c 3a 20 6e 6f 2d 63 61 63 68 65 0d 0a 0d  rol: no-cache...
00b0   0a 52 65 67 3d ×× ×× ×× ×× ×× ×× 26 56 65 72 3d  .Reg=××××××&Ver=
00c0   31 2e 31 30 2e 33 30 31 30 2e 31 34 26 41 75 74  1.10.3010.14&Aut
00d0   68 3d ×× ×× ×× ×× ×× ×× ×× ×× ×× 26 48 6c 61 3d  h=×××××××××&Hla=
00e0   ×× ×× ×× ×× ×× ×× ×× ×× ×× ×× 26 48 6c 6f 3d ××  ××××××××××&Hlo=×
00f0   ×× ×× ×× ×× ×× ×× ×× ×× ×× 26 54 74 3d 31 34 39  ×××××××××&Tt=149
0100   36 38 30 34 39 38 34 26 4c 69 6e 65 73 3d 35 26  6804984&Lines=5&
0110   6c 69 6e 65 30 30 30 31 3d 20 20 20 20 20 20 20  line0001=       
0120   20 20 20 20 20 20 20 20 20 30 36 41 30 43 31 20           06A0C1 
0130   20 20 20 20 20 20 20 20 20 20 20 20 20 20 30 2e                0.
0140   30 30 30 30 30 30 20 30 2e 30 30 30 30 30 30 20  000000 0.000000 
0150   20 20 20 20 20 20 30 2e 30 20 20 20 33 31 34 2e        0.0   314.
0160   30 20 20 20 34 39 30 2e 30 20 31 34 39 36 38 30  0   490.0 149680
0170   34 39 38 33 20 35 34 20 30 30 30 30 20 2d 36 34  4983 54 0000 -64
0180   26 6c 69 6e 65 30 30 30 32 3d 20 20 20 20 20 20  &line0002=      
0190   20 20 20 20 20 20 20 20 20 20 34 42 44 31 34 39            4BD149
01a0   20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
01b0   34 39 2e 37 36 35 31 33 34 20 20 20 32 30 2e 34  49.765134   20.4
01c0   32 36 38 35 30 20 20 20 32 30 36 30 30 2e 30 20  26850   20600.0 
01d0   20 20 33 31 36 2e 30 20 20 20 33 37 36 2e 30 20    316.0   376.0 
01e0   31 34 39 36 38 30 34 39 38 33 20 35 34 20 36 31  1496804983 54 61
01f0   34 34 20 2d 32 33 30 34 26 6c 69 6e 65 30 30 30  44 -2304&line000
0200   33 3d 41 55 41 36 39 30 20 20 20 20 20 20 20 20  3=AUA690        
0210   20 20 34 34 30 38 32 38 20 20 20 20 20 20 20 20    440828        
0220   20 20 20 20 20 20 20 20 35 30 2e 32 39 35 36 38          50.29568
0230   35 20 20 20 32 30 2e 33 36 38 32 31 39 20 20 20  5   20.368219   
0240   33 36 30 30 30 2e 30 20 20 20 32 32 31 2e 30 20  36000.0   221.0 
0250   20 20 33 38 34 2e 30 20 31 34 39 36 38 30 34 39    384.0 14968049
0260   38 33 20 35 34 20 36 32 35 32 20 30 26 6c 69 6e  83 54 6252 0&lin
0270   65 30 30 30 34 3d 53 44 4d 35 37 37 35 20 20 20  e0004=SDM5775   
0280   20 20 20 20 20 20 34 32 34 35 37 41 20 20 20 20        42457A    
0290   20 20 20 20 20 20 20 20 20 20 20 20 34 39 2e 36              49.6
02a0   37 34 37 32 39 20 20 20 32 31 2e 36 31 31 33 36  74729   21.61136
02b0   39 20 20 20 33 36 30 30 30 2e 30 20 20 20 31 39  9   36000.0   19
02c0   31 2e 30 20 20 20 33 37 39 2e 30 20 31 34 39 36  1.0   379.0 1496
02d0   38 30 34 39 36 33 20 35 34 20 34 35 32 35 20 30  804963 54 4525 0
02e0   26 6c 69 6e 65 30 30 30 35 3d 4c 4c 50 38 37 37  &line0005=LLP877
02f0   37 20 20 20 20 20 20 20 20 20 34 38 39 43 31 36  7         489C16
0300   20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0310   34 39 2e 35 30 30 30 30 30 20 20 20 32 30 2e 33  49.500000   20.3
0320   34 36 33 31 38 20 20 20 33 34 30 30 30 2e 30 20  46318   34000.0 
0330   20 20 31 38 32 2e 30 20 20 20 33 39 35 2e 30 20    182.0   395.0 
0340   31 34 39 36 38 30 34 39 38 31 20 35 34 20 34 35  1496804981 54 45
0350   33 31 20 30                                      31 0

Aircraft position available (printf-style):
"&line%04d=%8s        %06X               %10.6lf %11.6lf %7d.0 %5d.0 %5d.0 %d 54 %04X %d",
line_no++, a.flight, a.addr (ICAO), a.lat (latitude), a.lon (longitude), a.altitude,
a.track, a.speed, a.seenLatLon, a.modeA (Squawk), a.vert_rate

Empty aircraft position (printf-style):
"&line%04d=%8s        %06X               0.000000 0.000000 %7d.0 %5d.0 %5d.0 %d 54 %04X %d",
line_no++, a.flight, a.addr (ICAO), a.altitude, a.track, a.speed, a.seen, a.modeA (Squawk),
a.vert_rate
Fields are from struct aircraft.