In our robotics team, we have multiple programmers all working on the same robot. The robot is controlled by a REV Control Hub, which is just an Android device at heart. We write our code in Android Studio and send it over WiFi and ADB's TCPIP feature. The robot creates a WiFi network to which the driver station (another Android device that is used to wirelessly control the robot with gamepads) and the programming computers are connected to. There are multiple issues with this system: the robot's WiFi has no internet connection and multiple computers cannot send code to the robot at the same time without having the other computer first disconnect from the robot.


In the days of old, we sent code to the robot over a USB cable and debugged through that. Naturally, this was difficult to quickly develop when the robot was on the field. One year, we figured out how to send code over WiFi. We connected to the robot over USB and ran adb tcpip 5555. Disconnect from the robot and connect to the WiFi and connect to the robot through the WiFi: adb connect 192.168.49.1:5555. Easy enough. The one sacrifice we made of not having internet connection was fine.

However, when we have two, or three, or four programmers, using adb connect ... no longer works. It will remove the other people who are connected or just freezes up ADB. Our solution for the longest time was to just have one person programming, but this year we have more than two programmers and it's not feasible to have everyone working on the same laptop. Therefore, we needed to find a solution.

After scouring the internet, we learned that ADB is an example of the classic client-server model. There is an ADB server that is run and Android Studio and the ADB command line tool act as clients. So, can we have one ADB server and every other device can use that server. It's fairly simple to do. adb -a -P 5037 nodaemon server starts an ADB server that listens on port 5037 (the default ADB port) and listens on all network interfaces.

There is a simple(ish) Batch program that can be used to automate this for Windows.

@echo off
echo.

IF "%1" == "" GOTO noparams
IF "%1" == "start" GOTO start
IF "%1" == "stop" GOTO stop
IF "%1" == "/?" GOTO help
IF "%1" == "-h" GOTO help
IF "%1" == "--help" GOTO help

GOTO noparams

:start
    C:\Users\dell\AppData\Local\Android\Sdk\platform-tools\adb.exe kill-server
    START /B C:\Users\dell\AppData\Local\Android\Sdk\platform-tools\adb.exe -a -P 5037 nodaemon server
    echo.
    timeout /t 2
    C:\Users\dell\AppData\Local\Android\Sdk\platform-tools\adb.exe connect 192.168.43.1:5555
    GOTO end

:stop
    C:\Users\dell\AppData\Local\Android\Sdk\platform-tools\adb.exe kill-server
    GOTO end

:noparams
    echo Please give a command
    GOTO help

:help
    echo Usage: adb-sacrifice [command]
    echo.
    echo Generic commands:
    echo   start - Starts the server
    echo   stop - Kills the server
    GOTO end

:end
    echo.

Other devices, if they are connected to the same network, can connect to the ADB server through either a command line argument (ie adb -H [IP of server] -P [Port] [commands that you want to run]). The port option does not have to be used if ADB server is running on the default port of 5037.

The better solution is to set an environment variable instead: ANDROID_ADB_SERVER_ADDRESS=[IP] and ANDROID_ADB_SERVER_PORT=[Port]. Fairly simple to do in Windows, MacOS, or Linux.

However, Android Studio on Windows does not like to play nice with another device acting as an ADB server. The solution is both extremely stupid and smart. We forward all requests to localhost port 5037 to the other device with Windows commands. Running this command: netsh interface portproxy add v4tov4 listenaddress=127.0.0.1 listenport=5037 connectaddress=[IP of ADB server] connectport=5037 will forward all requests from localhost port 5037 to the IP address of the ADB server. Turning this off is another Admin command away: netsh interface portproxy delete v4tov4 listenaddress=127.0.0.1 listenport=5037. This is only a Windows issue! MacOS and Linux work fine with the environment variable set. A simple Batch program can also be used to automate this.

@echo off
echo.

IF "%1" == "/?" GOTO help
IF "%1" == "-h" GOTO help
IF "%1" == "--help" GOTO help
IF "%1" == "" GOTO noparams

:checkperm
    net session >nul 2>&1
    if NOT %errorLevel% == 0 (
        echo Rerun as admin
        GOTO end
    )

IF "%1" == "start" GOTO start
IF "%1" == "stop" GOTO stop

GOTO help

:start
  IF "%2" == "" GOTO noparams
  IF "%3" == "" GOTO noparams
  netsh interface portproxy add v4tov4 listenaddress=127.0.0.1 listenport="%3" connectaddress="%2" connectport="%3"
  GOTO end

:stop
  IF "%2" == "" GOTO noparams
  netsh interface portproxy delete v4tov4 listenaddress=127.0.0.1 listenport="%2"
    GOTO end

:noparams
    echo Please give a command
    GOTO help

:help
    echo Usage: adb-client [command]
    echo.
    echo Generic commands:
    echo   start [address] [port] - Sets up forwarding
    echo   stop [port] - Stops forwarding
    GOTO end

:end
    echo.

The next issue is how to have both internet connection and connection to the robot. This is a very simple solution: the ADB server needs to have a second WiFi adapter and connect to both the robot and the internet-enabled WiFi.

Network Diagram

Made with Draw.io. Source.

The client devices must connect to the IP address of the ADB server on the internet-enabled WiFi.

Fairly simple. Sure.

Previous Post