DJI Protocol – Packet Structure

Packet Structure

Layer 1 – 4

As the DJI Protocol – Packet Structure analysis is based on the DJI’s Wifi-Protocol, the first 42 bytes are related to Layer 1, 2, 3 and 4. As this is common knowledge and can be read up somewhere else, we won’t cover this section in detail. However, we do have some important bytes we would like to mention.

AddressBitsDescription
0x178Protocol Type – We are only interested in UDP packets. Hence, all received IP packets not equal to 0x11 aren’t important to us. It is worth mentioning as the drone and operator not only send UDP, but also ICMP packets.
0x1A – 0x3364IP-Addresses – Source and Destination IP-Address. The Wifi-Header does contain the sender and receiver as well, but we can already determine whether we deal with a drone or operator packet on layer 3.
List. 1.: Layer 3 important bytes

Wifi-Header

// this section is still work in progress

AddressBitsDescription
0x00 – 0x0116Packet-Length – The size of the entire UDP Payload. ((0x01 & 0x0F) << 8) + 0x00
0x02 – 0x0416Session Identifier – Each time you connect your operator to the drone, a session identifier will be randomly chosen, which will be consistent throughout the entire flight. This theoretically enables to remote control several different drones on one ground station.
0x068DUML-Type – The DUML’s content type. For more details see List. 2.
List. 2.: Wifi-Header description

DUML-Head

The DUML-Head (DJI Universal Markup Language) is the start of a valid and processable packet between the drone and operator. The DUML format is consistent throughout several drones and communication protocols. (I.e.: Bluetooth, SDR or Wifi) There might be some minor differences between drones (E.g.: custom delimiters, specific command-sets, etc.) but the core and structure remains the same.

AddressBitsDescription
0x008Delimiter – Indicates the start of a DUML packet. This delimiter depends on the drone. E.g.: 0x55 for Mavic Pro 1, Phantom 3, Phantom 4 or 0xAB for Phantom 1, Phantom 2, Naza M,…
0x01 – 0x026Protocol Version
0x01 – 0x0210Packet-Length – The length of the entire DUML packet; Payload-Header + Payload
0x038CRC – Checksum covering 0x00 – 0x02 (See List. 4)
List. 3.: DUML Head description
byte[] headerCrcHexTable = new byte[] { 0x00,0x5E,0xBC,0xE2,0x61,0x3F,0xDD,0x83,0xC2,0x9C,0x7E,0x20,0xA3,0xFD,0x1F,0x41,0x9D,0xC3,0x21,0x7F,0xFC,0xA2,0x40,0x1E,0x5F,0x01,0xE3,0xBD,0x3E,0x60,0x82,0xDC,0x23,0x7D,0x9F,0xC1,0x42,0x1C,0xFE,0xA0,0xE1,0xBF,0x5D,0x03,0x80,0xDE,0x3C,0x62,0xBE,0xE0,0x02,0x5C,0xDF,0x81,0x63,0x3D,0x7C,0x22,0xC0,0x9E,0x1D,0x43,0xA1,0xFF,0x46,0x18,0xFA,0xA4,0x27,0x79,0x9B,0xC5,0x84,0xDA,0x38,0x66,0xE5,0xBB,0x59,0x07,0xDB,0x85,0x67,0x39,0xBA,0xE4,0x06,0x58,0x19,0x47,0xA5,0xFB,0x78,0x26,0xC4,0x9A,0x65,0x3B,0xD9,0x87,0x04,0x5A,0xB8,0xE6,0xA7,0xF9,0x1B,0x45,0xC6,0x98,0x7A,0x24,0xF8,0xA6,0x44,0x1A,0x99,0xC7,0x25,0x7B,0x3A,0x64,0x86,0xD8,0x5B,0x05,0xE7,0xB9,0x8C,0xD2,0x30,0x6E,0xED,0xB3,0x51,0x0F,0x4E,0x10,0xF2,0xAC,0x2F,0x71,0x93,0xCD,0x11,0x4F,0xAD,0xF3,0x70,0x2E,0xCC,0x92,0xD3,0x8D,0x6F,0x31,0xB2,0xEC,0x0E,0x50,0xAF,0xF1,0x13,0x4D,0xCE,0x90,0x72,0x2C,0x6D,0x33,0xD1,0x8F,0x0C,0x52,0xB0,0xEE,0x32,0x6C,0x8E,0xD0,0x53,0x0D,0xEF,0xB1,0xF0,0xAE,0x4C,0x12,0x91,0xCF,0x2D,0x73,0xCA,0x94,0x76,0x28,0xAB,0xF5,0x17,0x49,0x08,0x56,0xB4,0xEA,0x69,0x37,0xD5,0x8B,0x57,0x09,0xEB,0xB5,0x36,0x68,0x8A,0xD4,0x95,0xCB,0x29,0x77,0xF4,0xAA,0x48,0x16,0xE9,0xB7,0x55,0x0B,0x88,0xD6,0x34,0x6A,0x2B,0x75,0x97,0xC9,0x4A,0x14,0xF6,0xA8,0x74,0x2A,0xC8,0x96,0x15,0x4B,0xA9,0xF7,0xB6,0xE8,0x0A,0x54,0xD7,0x89,0x6B,0x35 };

public static byte Crc8(byte[] data)
{
    var checkSum = 0x77;

    for (int i = 0; i < 3; i++)
        checkSum = headerCrcHexTable[((data[i] ^ checkSum) & 0xFF)];
 
   return (byte)checkSum;
}

DUML-Body

Let’s imagine that the drone isn’t a unified piece of hardware. Instead, consider a collection of hardware pieces, all self-contained, with an option for intermediate component communication. This aspect exemplifies different source- and destination endpoints for a UDP packet. Thus, the DUML-Body contains all relevant information required to enable intermediate component communication.

AddressBitsDescription
0x003Sender Index – Source component index
0x005Sender TypeSource component
0x013Receiver Index – Destination component index
0x015Receiver TypeDestination component
0x02 – 0x0316Sequence Counter – As UDP packets may arrive out-of-order, the Sequence Counter is a must have. The Sequence Counter will increment by 1 for each operator-to-drone packet, and for drone-to-operator packets a random value will be chosen to avoid duplicates.
0x041Request Type – Either Request 0 or Response 1
0x043AcknowledgementNoAck 000, Before-Execution 010, After-Execution 100
0x044Encryption – How the DUML-Tail is encrypted. There are several options available, but none of them will be used for the Wifi-Protocol, as the communication itself has already encryption (WPA2-PSK AES CCM) enabled.
0x058Command-Set – The set the command belongs to
0x068Command – The command within the Command-Set
List. 5.: DUML-Body description

DUML-Tail

Last, but not least, the DUML-Tail; The DUML-Head and DUML-Body do contain meta-information only. Therefore, the actual command’s content is present within the DUML-Tail.

AddressBitsDescription
0x00 – (n – 2)nCommand Payload – Most commands carry a specific payload. E.g.: Altitude, Rotation, Velocity, etc. This payload depends on the Command-Set and Command. The length of the payload can be calculated with:

x = DUML-Head[Packet-Length] n Bytes
a = DUML-Head-Size: 4 Bytes
b = DUML-Body-Size: 7 Bytes
c = DUML-Tail-Size: 2 Bytes

Payload-Length: x – (a + b + c) or in short: (0x01 – 0x02) & 0x3FF) – 13
(n – 1) – n16CRC – Checksum covering DUML-Body and DUML-Tail (See List. 7)
List. 6.: DUML-Tail description
private static readonly ushort[] bodyCrcHexTable = new ushort[] {0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c,0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974,0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb,0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3,0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a,0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72,0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9,0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1,0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738,0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70,0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7,0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff,0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036,0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e,0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5,0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd,0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134,0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c,0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3,0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb,0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232,0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a,0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1,0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9,0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330,0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78};

public static ushort Crc16(byte[] data) 
{       
    ushort checkSum = 0x3692;

    for (int i = 0; i < data.Length; i++)
        checkSum = (ushort)((checkSum >> 8) ^ bodyCrcHexTable[(data[i] ^ checkSum) & 0xFF]);

    return checkSum;
}}

Commands

Operator ➔ Drone

StatusProtocol-DetailsBlog-Entry
Connection HandshakeDay 6

Drone ➔ Operator

Status Protocol-Details Blog-Entry
Connection Handshake Day 6
0 0 votes
Article Rating
Subscribe
Notify of
1 Comment
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

[…] about both packets (operator to drone and drone to operator) have been documented and added to the packet-types enumeration. In short: we were able to detect two important values within the […]