I'm in the process of making a small program to read the control input from a USB gamepad and send the commands to the quadcopter but first I wanted to make sure I got the UDP protocol right. Therefore, I wrote a small Python script that can be combined with airodump-ng and tcpdump in order to read what the phone app is sending to the quadcopter by UDP and translate the controllers axes readings into something a human can read. The source code is attached below:
import sys state=0 message="" yaw=0 roll=0 pitch=0 throttle=0 commands=0 err=0 n=0 for line in sys.stdin: if state==0: pos=line.find("0x0010:") if pos!=-1: message=line[(pos+39):(pos+43)]+line[(pos+44):(pos+48)] roll=int(line[(pos+41):(pos+43)],16) pitch=int(line[(pos+44):(pos+46)],16) throttle=int(line[(pos+46):(pos+48)],16) state=1 else: state=0 pos=line.find("0x0020:") if pos!=-1: message=message+line[(pos+9):(pos+13)]+line[(pos+14):(pos+18)] yaw=int(line[(pos+9):(pos+11)],16) commands=int(line[(pos+11):(pos+13)],16) err=int(line[(pos+13):(pos+15)],16) n=n+1 if n==10: #this is a little trick that only displays 1 out of 10 messages sys.stdout.write(message+" roll:"+str(roll)+" pitch:"+str(pitch)+" throttle:"+str(throttle)+" yaw:"+str(yaw)+" commands:"+format(commands,"08b")+" err:"+format(roll^pitch^throttle^yaw^commands,'x')+'\n') n=0In order for this to work, the following commands have to be executed first:
# airmon-ng start wlan0 # airodump-ng -c 2 mon0The first command puts the wifi adapter into monitor mode and creates the monitor interface. I'm not sure if this can work while the network-manager is running, so I stopped the network-manager beforehand using /etc/init.d/network-manager stop (under Debian). The second command above starts sniffing the traffic in the wifi channel #2. At this point I would turn on the quadcopter, connect my phone to the quadcopter's wifi network and start the jjrc app and the bsid of the quadcopter should appear in the terminal where airodump is running. It will look like this:
CH 2 ][ Elapsed: 1 min ][ 2017-02-19 18:58 ][ WPA handshake: 42:D1:A4:C1:E5:A2 BSSID PWR RXQ Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID 01:C0:06:40:B2:32 -37 0 554 4901 0 2 54e. OPN JJRC-A21494F A4:E7:22:14:5B:CD -48 26 610 2 0 1 54e WPA2 CCMP PSK BTHub6-RFPMThe next thing to do is to start tcpdump and pass the UDP traffic between the phone and the quadcopter to my python script:
# tcpdump -i 2 udp dst port 8895 -x -l | python ./my_script.pyThis should produce an output that looks like this:
66807f0180007e99 roll:128 pitch:127 throttle:1 yaw:128 commands:00000000 err:7e 6667640180008299 roll:103 pitch:100 throttle:1 yaw:128 commands:00000000 err:82 6665630180008799 roll:101 pitch:99 throttle:1 yaw:128 commands:00000000 err:87 6665630180008799 roll:101 pitch:99 throttle:1 yaw:128 commands:00000000 err:87 66807f0080007f99 roll:128 pitch:127 throttle:0 yaw:128 commands:00000000 err:7f 66807f0080007f99 roll:128 pitch:127 throttle:0 yaw:128 commands:00000000 err:7f 66807f0080007f99 roll:128 pitch:127 throttle:0 yaw:128 commands:00000000 err:7f 66a6770080005199 roll:166 pitch:119 throttle:0 yaw:128 commands:00000000 err:51 66a6770080005199 roll:166 pitch:119 throttle:0 yaw:128 commands:00000000 err:51 6671620080009399 roll:113 pitch:98 throttle:0 yaw:128 commands:00000000 err:93 666b840080006f99 roll:107 pitch:132 throttle:0 yaw:128 commands:00000000 err:6f 66978e0080009999 roll:151 pitch:142 throttle:0 yaw:128 commands:00000000 err:99 66807f0080007f99 roll:128 pitch:127 throttle:0 yaw:128 commands:00000000 err:7f 66807f0080007f99 roll:128 pitch:127 throttle:0 yaw:128 commands:00000000 err:7fBy the way, I found out that the difference between the 30%, 60% and 100% settings in the app is the range of the roll and pitch control inputs one gets, they go from 1 to 255 when in 100% mode, from 68 to 187 in 60% mode and from 88 to 167 in the 30% mode. The throttle and yaw controllers are unaffected by the 30/60/100 mode setting.