ABOUT THE JJRC H37 ELFIE
For those who don't know the toy, the JJRC H37 Elfie is a cheap wifi-controlled FPV quadcopter (https://www.google.co.uk/search?q=jjrc+h37+elfie). The toy comes with an app for Android and iOS. The way you normally start playing with the quadcopter is the following: you connect the battery to the quadcopter, press the On button in the quadcopter, connect to the wifi network of the quadcopter from your phone (it is called "JJRC-something") and open JJRC's app. Once the app is on, you get to see what the camera of the quadcopter is seeing and then you can enable the on-screen controls, turn on the propellers and start flying the quadcopter. If you want to see this for yourself you may check one of the 1,000 reviews available in Youtube (https://www.youtube.com/results?search_query=jjrc+elfie).
PLEASE NOTE: THE TEXT BELOW IS OBSOLETE NOW THAT I'VE MANAGED TO MAKE THIS WORK. I'LL UPDATE THE TEXT SOON! (check the project log for more details)
ABOUT THE PROJECT
I was curious to find out how the application communicated with the quadcopter because I thought perhaps I'd be able to control the quadcopter from the internets or use a wifi repeater with a better antenna than my phone in order to extend its range. In the end, I used airodump-ng to find out what the channel of the quadcopter's wifi was and start monitoring the channel to dump all traffic between the quadcopter and my mobile phone using wireshark.
What I found out is that as soon as the JJRC application is opened, a continuous TCP communication is established between the quadcopter and the phone. This is the means the video stream is sent from the quadcopter to the phone. However, surprisingly enough, this communication persists even if the video is not being shown in the screen or the JJRC application is running in the background (Android).
Another detail I found out is that as soon as one presses the button to enable the "altitude hold" or the "on-screen controllers" in the mobile app, a UDP connection is established between the mobile phone and the quadcopter on port 8859. As soon as this connection is established and while this connection is on, the blinking pattern of the lights of the quadcopter changes. This connection remains active as long as the controllers are visible in the screen of the app and the altitude hold hasn't been disabled. Looking at the traffic in this UDP connection, the mobile phone seems to send an 8 byte packet to the quadcopter every 50 milliseconds.
STATE OF THE PROJECT
A detailed explanation of each of the following things can be found in my project logs. So far I've managed to do the following:
- Wi-Fi Repeater: Use a computer running Debian with two wifi cards to be a man-in-the-middle with a strong wifi antenna that interfaces the phone to the quadcopter at greater distances. This adds a bit of latency but the response is still good enough to control the quadcopter to wander at relatively mild speeds with no wind.
-Control the quadcopter from a PC with a USB gamepad without the phone (no video): this can be done by connecting the PC to the quadcopter via wifi and sending properly formatted UDP packets. This was very easy to implement and works like charm.
FURTHER STEPS / TO-DO
- Watch the video stream from a PC: The next thing I want to do is to be able to view the camera stream from the PC. The phone app seems to open multiple connections to the quadcopter and sends multiple 160 byte long messages that nobody seems to know what they mean. One of the connections is replied back by the quadcopter with the video stream and the 160 byte long message that initiates this process seems to be the same every time. I haven't tested that yet but it should be possible to open a TCP socket to the quadcopter, send the magic word and direct the quadcopter's response to mplayer or vlc.
I've been looking at my JJRC H68 drone, or more precisely its detachable camera and WiFi control module (the drone works fine without it, using the included controller; I've been using the camera with an RC car).
The IP address is 172.16.1.1. Video is TCP from port 8888.
I can capture with:
cat vidstream-trigger - | nc 172.16.1.1 8888 > video.out
where vidstream-trigger contains the magic hex bytes 00 01 02 03 04 05 06 07 08 09 28 28. And your ffmpeg conversion works fine on the output.
I think UDP commands are different--if memory serves, they are 11 bytes long. Port is still 8080.
The camera runs linux. You can also telnet 172.16.1.1. Username: root, no password. I haven't found anything particularly interesting to do with the root shell.