Using a TP-Link WR703n with an Arduino

Arduino's are cheap, infinitely useful microcontrollers. Log and react to temperatures, humidity, sound, movement, light, air pollution and on and on and on. Unfortunately, for continuous data collection you either need to write data to an SD card (not the greatest solution because eventually you'll need a physical connection to get the data), have a dedicated PC (obviously expensive although with a Raspberry Pi it's an option) or use a network connectivity shield. The wifi shields presumably work well (I haven't tried one), but at ~$40 their value proposition is difficult to make, you might as well just get a Raspberry Pi. So far the cheapest method that I've found for connecting an Arduino to the internet is to buy a cheap travel router, specifically the TP-Link WR703n.

The WR703n router is $20, small (about 1inch x 1inch x 1inch), has barely enough memory to store the firmware, but is rock solid once set up and perfect for data exchange between an Arduino and the net. The router has a USB port that can also power the Arduino. Doubling as a power source for the Arduino is especially useful because it makes everything that much more compact.

So why isn't everybody using one of these? Because they're quite tricky to configure and it relies on the ability to replace the firmware with custom firmware, openwrt. This would be easier to do if 1) the pre-installed firmware wasn't in Chinese (or if you could speak Chinese) and 2) the new versions didn't actively prohibit you from installing openwrt. Below you'll find instructions on installing openwrt on this router.

Check the pre-installed firmware version

If it says v1.7, then read on for install instructions. If you have v1.6, then install openwrt using instructions here and use this firmware version of openwrt (Attitude Adjustment, non trunk). After installing, come back to learn how to hook it up to the Arduino.

Installing OpenWRT when v1.7 stock firmware is present

Installing OpenWRT when v1.7 of the stock firmware is present isn't easy to do. It's based on an exploit in the parental controls of the stock firmware. Here are step-by-step instructions of how to do it, with a focus on doing this from Mac OS Yosemite. These instructions are based on other people's work, but I've summarized them and commented on my own experience with this. These are good references to read through:

Overview of tasks

The installation is done by running a script on the WR703n router which copies the firmware from your PC onto the router, and then installs the firmware. The file transfer process is done via tftp which is a bare bones ftp service. Your PC will be running the tftp server and the WR703n will connect and download the files it needs. To actually run the install script on the WR703n, you have to exploit a bug in the stock firmware which allows you to inject code onto the router and run the script. This part is done which the curl command. Once the script has finished running, you should have OpenWRT installed on your WR703n router, and you can then set the router up any way you want (assuming you stay within the very tight memory limits of the WR703n).

Step 1. Collect the tools

As per these instructions:

  • Download openwrt [download]
  • On a mac, you'll already have curl, dd and tftp installed, but I had problems getting tftp up and running and so I would recommend installing the graphical user interface for tftp, tftp server [download]

Step 2. Prepare the files on your PC

On a mac, the tftp server root directory is /private/tftpboot. All of the files that get downloaded onto the WR703n router will be there.

  • First make sure /private/tftpboot is writeable and readable:
    $ chmod 777 /private/tftpboot
  • Create the script file called aa and place it in /private/tftpboot:
    # /private/tftpboot/aa
    cd /tmp
    tftp -gl i1 192.168.1.100
    tftp -gl i2 192.168.1.100
    tftp -gl busybox 192.168.1.100
    chmod 755 busybox
    ./busybox dd if=i1 of=/dev/mtdblock1 conv=fsync
    ./busybox dd if=i2 of=/dev/mtdblock2 conv=fsync
    ./busybox reboot -f
    
  • Copy the openwrt firmware that you downloaded in step 1 into the /private/tftpboot directory and split it into 2 sections:
    $ dd if=/private/tftpboot/openwrt-ar71xx-generic-tl-wr703n-v1-squashfs-factory.bin of=/private/tftpboot/i1 bs=1 count=1048576
    $ dd if=/private/tftpboot/openwrt-ar71xx-generic-tl-wr703n-v1-squashfs-factory.bin of=/private/tftpboot/i2 bs=1 skip=1048576
  • Download the busybox set of command line utilities so that they can be used by the stock firmware on the WR703n:
    $ curl http://busybox.net/downloads/binaries/latest/busybox-mips > /private/tftpboot/busybox
  • In your /private/tftpboot directory (on your mac), you should now have the following files: aa, i1, i2, busybox, openwrt-ar71xx-generic-tl-wr703n-v1-squashfs-factory.bin

Step 3. Run the tftp server on your mac

Use the TFTP Server GUI downloaded in Step 1 to start your tftp server on your mac.

Step 4. Inject the aa script onto the WR703n

Using ethernet, plug the WR703n router into your computer. Make sure that when you browse to http://192.168.1.1 you connect to the factory firmware of your WR703n router. Your computer should have received an IP address from the router. Mine was given 192.168.1.100. Check your computer's IP and update the /private/tftpboot/aa script with the IP address that you were assigned (just replace 192.168.1.100 with your IP address).

You should now be ready to inject the script using the following commands (don't unplug anything during this process!):

  1. In the terminal, make sure you're in the tftp root directory:
    $ cd /private/tftpboot
  2. Set the password on your WR703n to admin123:
    $ curl -o - -b "tLargeScreenP=1; subType=pcSub; Authorization=Basic%20YWRtaW46YWRtaW40Mg%3D%3D; ChgPwdSubTag=true" "http://192.168.1.1/"
  3. Turn on parental controls on WR703n (required for the script injection):
    $ curl -o - -b "tLargeScreenP=1; subType=pcSub; Authorization=Basic%20YWRtaW46YWRtaW40Mg%3D%3D; ChgPwdSubTag=" --referer "http://192.168.1.1/userRpm/ParentCtrlRpm.htm" "http://192.168.1.1/userRpm/ParentCtrlRpm.htm?ctrl_enable=1&parent_mac_addr=00-00-00-00-00-02&Page=1"
  4. Upload the aa script to the router and run it:
    $ curl -o - -b "tLargeScreenP=1; subType=pcSub; Authorization=Basic%20YWRtaW46YWRtaW40Mg%3D%3D; ChgPwdSubTag=" --referer "http://192.168.1.1/userRpm/ParentCtrlRpm.htm?Modify=0&Page=1" "http://192.168.1.1/userRpm/ParentCtrlRpm.htm?child_mac=00-00-00-00-00-01&lan_lists=888&url_comment=test&url_0=;cd%20/tmp;&url_1=;tftp%20-gl%20aa%20192.168.1.100;&url_2=;sh%20aa;&url_3=&url_4=&url_5=&url_6=&url_7=&scheds_lists=255&enable=1&Changed=1&SelIndex=0&Page=1&rule_mode=0&Save=%B1%A3+%B4%E6"
Hopefully the aa script has run and the files have been transferred from your pc to the router, the script should have installed OpenWRT and rebooted the router. You should now have OpenWRT installed!

Step 5. Install u-boot

You should now have OpenWRT installed. First of all, telnet into the router and set a password:
$ telnet 192.168.1.1
$ passwd
$ exit
This is the end of part 1! You should now be able to ssh into the router as root with your new password.

Installing u-boot is optional but recommended because it'll help prevent bricked routers. Instructions for u-boot are here and worked well for me. To move the firmware from your pc to the WR703n, you can use the scp command:
$ scp file.bin root@192.168.1.1:/tmp/file.bin

Interfacing the WR703n with an Arduino

The approach that I took was to just plug the Arduino directly into the usb port of the WR703n...and it worked! I initially wanted to communicate with the Arduino using python like I've done before with the Raspberry Pi but the WR703n doesn't have enough disk space for this. So the option that I chose was to use ser2net to open up a serial connection between the Arduino and the WR703n.

One thing that I've noticed is that the newer versions of OpenWRT seem to use up too much disk space on the WR703n. We need enough room for the OS and for a few packages. I've only been able to get OpenWRT version Attitude Adjustment (12.09) working, and that's good enough for me.

Step 1. Install Attitude Adjustment OpenWRT

Download OpenWRT v 12.09 for the WR703n. Then you need to copy over the firmware and use the mtd -r write command to install it:

  1. Copy the firmware to your router:
    $ scp openwrt-ar71xx-generic-tl-wr703n-v1-squashfs-factory.bin root@192.168.1.1:/tmp/
  2. Install the firmware:
    $ ssh root@192.168.1.1
    $ cd /tmp
    $ mtd -r write /tmp/openwrt-ar71xx-generic-tl-wr703n-v1-squashfs-factory.bin firmware

This should install Attitude Adjustment version of OpenWRT on your WR703n. Telnet into your router again to set the password (as in the first part of Step 5) and then browse to http://192.168.1.1 to make sure that the luci web interface is working and that you can log in with the password you supplied.

Step 2. Install ser2net on your WR703n

opkg install ser2net
[to be completed soon-ish, stay tuned]