Standalone OpenWRT Fadecandy Server for LED control

I recently discovered Micah’s awesome Fadecandy USB controller for WS281x LED pixels. One of the things that I like the most about it is its “fcserver” to control LED pixels using Websockets. That is fantastic, but all implementations I’ve seen have people running it on a RaspberryPi or regular PC.

I wanted to create a sort of “stand-alone” and embedded version of this using less expensive TP-Link routers, running OpenWRT. My current favourite of these is the TP-LINK TL-MR3040 but it would work just as well with the infamous WR703n or others; so long as they have USB support.

To do this, I created an OpenWRT package of the fcserver code: https://github.com/nemik/fadecandy-openwrt
You can add this to your own OpenWRT build by adding the line src-git fadecandy git://github.com:nemik/fadecandy-openwrt.git to your “feeds.conf.default”. Then run ./scripts/feeds update -a, then ./scripts/feeds install -a. Then run make menuconfig. Select “fcserver” from “Utilities” and your target architecture/device. Then run make

Or, just get my pre-built binaries from here:
TP-Link MR3040 v1
TP-Link MR3040 v2
TP-Link MR3020
TP-Link WR703N

and flash them to your unit.

The defaults are:
* root password is “root”
* Open wifi access point called “Fadecandy” is broadcast. You can connect to it and get an IP
* The ethernet port is configured to accept DHCP leases, so if you plug it into your local router, it can give it an IP and you can get to it remotely then

That’s it. Then just plug in the Fadecandy USB device into your OpenWRT device’s USB port. It should detect it. Then you can connect to its “Fadecandy” access point over Wifi and visit “fadecandy:7890″ to get to the Fadecandy server interface.
Unfortunately, my WS2812 LEDs and Fadecandy controller have not yet arrived, but I do have a Teensy3. When I flashed it with the Fadecandy firmware version 1.07 (using TeensyLoader) it worked and blinked to identify itself from the web UI!
So I think that means it is working? If anyone could try it out with their pixels, please let me know how it works out for you. I hope performance is alright. Otherwise, I’ll be reporting back on it once my equipment arrives.

I like this approach because the OpenWRT units are very cheap, small, low power, and provide great connectivity. They also use a 5V source like many LED pixel strings, so they can be more easily integrated and embedded into art pieces and installations.

Whitelisting IPs in Apache and RHEL

I had a problem recently where I wanted to whitelist a set of IPs (and that set may change anytime) to allow them to use a reverse-proxy on Apache in an RHEL (Red Hat Enterprise Linux) environment. Here’s some instructions on how to do this yourself.

1. So the first step is to edit your Apache config. I was doing this in an SSL context so I edited the /etc/httpd/conf.d/ssl/conf file and put this in the VirtualHost part:
RewriteEngine On

RewriteMap ipslist txt:/var/www/whitelist.txt
RewriteCond %{REMOTE_ADDR} ^(.*)$
RewriteCond ${ipslist:%1|black} ^black$ [NC]
RewriteRule ^ - [F]

The first line turns on Apache’s Rewrite module, this is required for this setup to work. Then it creates a RewriteMap called ‘ipslist’ located at /var/www/whitelist.txt. I advise putting this in /var/www because if done in some other /home directory, it won’t work with SELinux enabled as it won’t allow Apache to access files there. Chmod’ing the whitelist.txt to 664 is a decent permission.

2. Create your whitelist. This is the “/var/www/whitelist.txt” file. For this, just put in the IP you want whitelisted followed by a space then “white”. Then the next IP on the next line.
So a sample one could be:
192.168.1.1 white
55.44.33.22 white

and so on.

3. Restart Apache, just do “sudo /etc/init.d/httpd restart”

4. That should be it! All the rest of your config can be as it is, including proxying functionality or whatever because the URL rewriting happens before all that.

The nice thing about the “RewriteMap” function is that you can change the whitelist.txt anytime you want and you don’t have to restart or reload Apache! It’ll automatically pick up on the change from the file’s changed date and update it.

Belkin Wemo Teardown part 2

Made progress today with using UPnP to communicate with the Wemo.

I used the awesome miranda-upnp Python library to explore the device. Its URL for listing services is at http://10.22.22.1:49152/setup.xml

There are ones for “rules”, “remoteaccess”, “metainfo”, “WiFiSetup”, “firmwareupdate”, “timesync” and “basicevent”.

The most interesting one, I’m guessing, is “basicevent” because it contains an action called “SetBinaryState” and “GetBinaryState” on top of others like “GetSerialNo”, “GetMacAddr” etc. But the BinaryState thing looks cool because I’m guessing it is what is used to control the switch.

Unfortunately, sending commands/actions to this service always returns a 500 error, with error code -111 is “Invalid Service” although from all indications I am sending the SOAP request to the proper URL and service. I tried it manually and through miranda-upnp, same results.
At this point I think it is a header I might be missing, perhaps the “User-Agent”? And without the one the device is expecting, it will reject with a 500?

I unfortunately don’t have an iOS device to test with. Has anyone with an iOS device and Belkin Wemo sniffed the traffic between them? If I can get my hands on one, next step would be use Ettercap and Wireshark on that same wifi AP to see what the iOS app is sending that I’m not.

Belkin Wemo Teardown part 1

I received a Belkin Wemo device today to play with.

Since I do not have an iOS device, and for some reason the Wemo ONLY works with iOS (wtf?), I’m trying to get it working without it.

So far I’ve connected my laptop to its wifi access point. It assigned me an IP of 10.22.22.2 and its IP is 10.22.22.1
No conventional ports such as 22/SSH, 23/Telnet or 80/HTTP worked.

Running nmap revealed very few ports to be opened:

nemik@a64:~$ nmap -sT 10.22.22.1

Starting Nmap 5.21 ( http://nmap.org ) at 2012-07-16 17:48 CDT
Nmap scan report for 10.22.22.1
Host is up (0.029s latency).
Not shown: 998 closed ports
PORT      STATE SERVICE
53/tcp    open  domain
49152/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 1.81 seconds

When running telnet on the opened port 49152, there were interesting things:

nemik@a64:~$ telnet 10.22.22.1 49152
Trying 10.22.22.1...
Connected to 10.22.22.1.
Escape character is '^]'.
HTTP/0.0 400 Bad Request
SERVER: Linux/2.6.21, UPnP/1.0, Portable SDK for UPnP devices/1.6.6
CONTENT-LENGTH: 50
CONTENT-TYPE: text/html
<html><body><h1>404 Not Found</h1></body></html>
Connection closed by foreign host.

Same for curl:

nemik@a64:~$ curl -i 10.22.22.1:49152
HTTP/1.1 404 Not Found
SERVER: Linux/2.6.21, UPnP/1.0, Portable SDK for UPnP devices/1.6.6
CONNECTION: close
CONTENT-LENGTH: 48
CONTENT-TYPE: text/html
<html><body><h1>404 Not Found</h1></body></html>

Interesting that it runs Linux though! I’d like to open it up to see the type of chips used inside but I do not have the triangular screwdriver for Belkin’s weird security screws on the device. If/when I order some and get it opened, I’ll post pics.

The next step is to borrow an iOS device and see if I can sniff the traffic for initializing the device. If anyone has done something similar or has any tips, please let me know.

Error mounting some SD cards on Linux Kernel 3.3+

I ran into an issue today using the gpiommc and mmc_spi kernel modules to use SD cards from GPIO pins, in OpenWRT.

Using a 2GB Transcend card I was getting:

[ 1473.570000] gpio-mmc: GPIO based MMC-Card "default" removed
[ 1473.960000] gpio-mmc: Failed to request mmc_spi module.
[ 1474.030000] mmc_spi spi32757.0: ASSUMING 3.2-3.4 V slot power
[ 1474.100000] mmc_spi spi32757.0: SD/MMC host mmc0, no DMA, no WP, no poweroff
[ 1474.190000] gpio-mmc: MMC-Card "default" attached to GPIO pins di=1, do=3, clk=4, cs=2
[ 1477.420000] mmc_spi spi32757.0: setup: unsupported mode bits 4
[ 1477.490000] mmc_spi spi32757.0: can't change chip-select polarity
[ 1477.960000] mmc0: error -145 whilst initialising SD card
[ 1478.030000] mmc0: card claims to support voltages below the defined range. These will be ignored.
[ 1478.210000] mmc0: unrecognised CSD structure version 0
[ 1478.270000] mmc0: error -22 whilst initialising MMC card

With more debugging, it turns out the “mmc_read_switch” function in the “drivers/mmc/core/sd.c” file was returning an error -145 with that SD card. Not sure why, either the CARD doesn’t support it? I can’t even find that error code anywhere so not really sure what the root reason is.
BUT when just doing a “return 0;” there, the SD card ends up mounting perfectly and working quite well.

This same SD worked in kernel 2.6.30 but its “mmc_read_switch” function was simpler and probably didn’t try to read all the extra info that the 3.3+ one is and erroring out on. Not getting this info didn’t seem to impact anything much.

I hope this helps someone if they’re looking for a fix for a similar issue.

Setting up a KillerBee

Having recently ordered an Atmel AVR RZ Raven kit I was curious to play with it and try to develop some 6LoWPAN applications. This was mainly done with Contiki OS using the EXCELLENT tutorial on it here: http://www.wsncloud-murdoch.org/wiki/index.php/ConfigurationofAtmelRavenswith_Contiki

I also wanted to get the KillerBee framework working. Contrary to what the KillerBee documentation says, you don’t really need an AVR JTAG ICE whatever $300 programmer. It works just fine the Atmel AVR Dragon which is only $50 USD.

Using that programmer, I was able to successfully flash the AVR Raven USBstick to the KillerBee firwmare using:

sudo avrdude -c dragonjtag -p usb1287 -e -P usb
avrdude -p usb1287 -c dragon
jtag -P usb -U flash:w:kb-rzusbstick-001.hex

I’m now able to use the zbdump tool and the others to sniff on ZigBee traffic. This is a lot of fun and seems there’s quite a few ZigBee and 6LoWPAN devices around here in River North in Chicago.

Arduino + OpenWRT = Art

It’s an OpenWRT image for the very cheap TP-Link TL-WR703N Linux routers you can buy from here: http://www.dealextreme.com/p/tp-link-703n-ultra-mini-portable-3g-802-11b-g-n-150mbps-wifi-wireless-router-light-blue-white-102903

What’s cool about them is that with the OpenWRT (https://openwrt.org/) Linux operating system, you can make this router do whatever you want, including broadcast a Wifi access-point, run Linux applications, etc. The REALLY cool thing is that it has a fully working USB port too! This means you can connect various devices to it such as USB storage, Arduinos, Launchpads, etc and even multiples of them on hubs.

I made a ready firmware version for the router that is configured to do this http://nemik.net/tmp/openwrt-ar71xx-generic-tl-wr703n-v1-squashfs-sysupgrade.bin

It is designed to make the TL-WR703N talk directly to Arduino’s and MSP430 Launchpad microcontroller kits by simply plugging in the kits into the USB port. Older Arduino’s will use FTDI drivers and make a /dev/USB0, new Arduino UNO’s make a /dev/ttyACM0, and TI’s MSP430 Launchpads make a /dev/ttyACM0 device. You can talk serial to them all directly then!
Just set the baud rate by doing something like:

stty -F /dev/ttyUSB0 raw speed 9600

and replace /dev/ttyUSB0 with /dev/ttyACM0 for Arduino UNO’s and TI Launchpad kits and 9600 with the baud rate you programmed your kit/sketch to.

You can read serial data from the kits with something like

cat /dev/ttyUSB0

and write to it simply by doing

echo "hello world" > /dev/ttyUSB0

I also packaged in SQLite and some other stuff I found useful. The .config can be found at http://nemik.net/tmp/openwrt_arduino.config

The Launchpad USB support comes from a new patch I submitted here: https://lists.openwrt.org/pipermail/openwrt-devel/2011-November/012919.html which I hope can get added to the trunk if it’s OK. It enables those drivers in the kernel, they’re already part of the kernel source.

This is not bad to use if you know your way around Linux. I disabled wireless on it and by default it listens for telnet until you set a root password for SSH with ‘passwd’.
Its subnet is 192.168.3.1 and if you plug a computer into its LAN port, it should issue an IP by DHCP on the 192.168.3.x subnet.

I hope it is useful for someone.

For an example, I used it to help a friend with an interactive art installation. It’s an art installation in Chicago called “Hatchery”. The website for it is here: http://www.popupartloop.com/active.php?id=123
It’s a sculpture inside a glass building with two photosensors on the outside measuring light. When a person places their hand on one of the sensors, it detects it because the difference between them is greater than some threshold (ADC’s are needed for this part) and then as the hand is held there, it starts a cool LED light sequence. If we make a video for it, I’ll post it here later.
Anyway, what also happens is that when the hand is placed there, the Arduino sends a serial string with something like “Touched!”. A program running on the WR703n (to which the Arduino is hooked up with over USB) listens for this and when it gets it, logs it to an SQLite database that resides on a large USB stick. The router also broadcasts a wireless access point that I can connect to from my Android phone and hit a certain URL to download that SQLite DB whenever I walk by. It’d be nicer to make it available direct on the internet but there are no public access points in the area for it to connect to.
Then I take the SQLite DB and do some queries on it to do a few simple analytics such as how many people touched it at what times, hours, days, etc. The analytics page is available here: http://nemik.net/hatchery/

I hope it’s some inspiration make your own networked devices using Launchpads and these unbelievably cheap yet powerful Linux machines.

Generate your own One Time Passcodes (OTP) to use with Android

  1. Download and build “otptool” from http://code.google.com/p/mod-authn-otp/wiki/OTPTool with the usual dance:
    ./configure
    make
    make install
  2. Download and install the Google Authenticator application from the market: https://market.android.com/details?id=com.google.android.apps.authenticator&hl=en on your Android phone
  3. Make up a hex-based secret for the two, like ’12345678901234567890′
  4. Base32 encode the secret:
    python -c "import base64,binascii; print base64.b32encode(binascii.unhexlify('12345678901234567890'))"
  5. Open the Google Authenticator app and manually add an account. Put whatever you want for the account name. For the Key, enter the output from step 4. Make sure it is ‘Time based’, Save.
  6. You’ll see a code in the app that rotates every 30 seconds.
  7. run otptool -t '12345678901234567890' or whatever secret you chose.
  8. Should be the same as on the app! Make sure your time is synced and correct on both devices.