Saturday, September 12, 2009

Droplet on the SheevaPlug



Droplet requires a Java service to listen for requests from remote Droplets and run background threads for push services. At first I used my notebook to run the service, but it wasn't very convenient since it tended to not stay put, or powered on for very long. Around this time I received a SheevaPlug, after a 1.5 month wait. The SheevaPlug is a low power, compact, ARM based Linux computer and is perfect for running the Droplet service. In this blog entry I describe how to get the Droplet service running on the SheevaPlug.

Setup

If you are using a FTDI usb-serial device to interface with XBee (e.g. XBee Explorer USB), you'll need to upgrade the kernel since the kernel shipped with the plug does not have usb-serial driver support. (Arduino uses the same FTDI usb-serial chip). Fortunately, for those of us not comfortable with compiling Linux, there are prebuilt kernels available with usb-serial support. Here's the wiki entry that describes the installation process.

The SheevaPlug only has 512MB of disk space, so you can quickly run out of disk space after installing a few packages (Java itself requires over 300MB). The solution to this problem is to install an SD card as your primary file system. This step is optional but strongly recommended for the reason that in addition to more disk space, the plug will also run quite a bit faster. Here's a guide that explains how to add an SD card.

Since this is an ARM computer and not x86, we can't simply install Sun's version of Java for Linux. Fortunately Sun open-sourced Java several years ago and the folks at Sun and RedHat have been hard at work on OpenJDK, rewriting the proprietary parts and porting it to additional architectures (ARM, MIPS, PowerPC etc).

Install OpenJDK

apt-get install openjdk-6-jdk
Install RXTX. RXTX provides serial port communications for Java applications

apt-get --no-install-recommends install librxtx-java
Now we are ready to install Droplet.

Make a folder for the application. I'm using "/root/apps/droplet". Zip up your Eclipse project, transfer it to the plug and unzip in the new folder.

Since we don't have Eclipse on the plug, we need a script to start the application. Create the following script and in a file called droplet.sh

#!/bin/bash

# application entry point
MAIN_CLASS=com.rapplogic.droplet.impl.DropletDemo

# specify path to the rxtx jar.  default is for librxtx-java
RXTX_JAR=/usr/share/java/RXTXcomm.jar

# location of rxtx modules when installed with apt-get
RXTX_LIB_PATH=/usr/lib

# FTDI should appear as /dev/ttyUSB0 if this is the only USB device
COM_PORT=/dev/ttyUSB0

# build classpath
JAR_LIST=`find lib -name '*.jar'`

# add all jar libraries to classpath
for file in $JAR_LIST
do
#echo "adding $file to classpath"
CLASSPATH=$CLASSPATH:$file
done

# append droplet compiled classes (bin) and rxtx jar to classpath
CLASSPATH=$CLASSPATH:bin:$RXTX_JAR

# start Java with a 16MB heap, using the Cacao JIT compiler
java -cacao -Xms16m -Xmx64m -classpath $CLASSPATH -Djava.library.path=$RXTX_LIB_PATH $MAIN_CLASS $COM_PORT 2> droplet.err 1> /dev/null
Make the script executable:

chmod u+x droplet.sh
Note: I'm running the application as root. This probably isn't a good practice but the plug is running inside my firewall, with no ports open to the public, so I think it's fine.

Since we installed RXTX with the lib-rxtx package, we want to remove the RXTX Java library from the project so we don't have multiple RXTX libraries in the classpath.

rm lib/RXTXcomm.jar
And for good measure remove the RXTX native Linux library.

rm librxtxSerial.so
You should now be able to to start Droplet:

./droplet.sh
Check the log if things aren't working as expected (log file is ./logs/droplet.log). Go ahead an kill the app (Ctrl-c).

We are not quite done yet. To have the application start whenever the SheevaPlug boots, we need to add a startup hook. But first we'll need to create another script to start the application in the background. Save this script as droplet-nohup.sh

#!/bin/bash

cd /root/apps/droplet/
nohup ./droplet &
Make it executable

chmod u+x droplet-nohup.sh
To add the startup hook, insert a call to the droplet-nohup.sh script at the end of the "do_start" function in /etc/init.d/bootmisc.sh

# startup droplet
sudo /root/apps/droplet/droplet-nohup.sh
Now reboot the plug and it should automatically start Droplet.

Performance

The performance of OpenJDK Java on the plug is not great but mostly sufficient. I had to rewrite the Twitter service, replacing XPath with StAX because the XPath implementation was consistently timing out. It was taking 20 seconds or more just to parse the friends's timeline! In comparison, the StAX implementation completes in about 5 seconds. In hindsight I could have used JSON, which is quite fast and is already used for Twitter search.

One possible explanation for the slow performance is the lack of Hotspot in OpenJDK. A significant portion of Hotspot was written in assembly, making it very difficult to port. The IcedTea project has been working to address this gap, first with Zero and now with Shark, which is based on LLVM. See this article for more information.

What Else?

I've been running Droplet on the SheevaPlug for the last couple weeks. Overall I've been quite pleased although there is one issue that has popped up a few times. For no apparent reason the Twitter service thread will block indefinitely on what appears to be the HTTP call. When this occurs the rest of the app continues to function but you won't see new Tweets. If you encounter this issue just restart the app.

You may need to adjust the timeout if you are getting "Application Timeout" messages. Usually this will only occur for the Twitter services. This is a two step process. First open the Arduino Sketch and adjust the following line:

#define APPLICATION_TIMEOUT 7500
Then open Droplet.java and adjust the timeout:

private long serviceTimeoutMillis = 6000. 
The Arduino timeout will always need to be about 1.5 seconds longer than the Java timeout to account for the packet roundtrip transmission time. Unless you have installed the Java compiler on the plug, you'll need to make this change in Eclipse, then copy the "bin" folder to the plug.

Now that you are using the only USB port, if you need additional ports you can add a USB hub. I've found that the Belkin F5U407 USB hub works great with the SheevaPlug. Keep in mind you should not be drawing much power from the USB hub, unless you are using a powered hub.

Conclusion

So now you have an always on Droplet service! Place your plug at the back of your desk, or anywhere you have an ethernet connection and forget about it. You should be able to place Droplet remotes anywhere, within range, and they will just work. Of course since the SheevaPlug is a general purpose Linux computer, you can use for other purposes, web server, file server etc.

Update: I installed a 90 day evaluation of Sun's Java SE for Embedded and the performance is now significantly improved. They have several different versions but the one that's compatible with the SheevaPlug is Java SE for Embedded 6.0 Update 10 ARMv5 Linux Early Access, EABI, glibc 2.5, Soft Float, Little Endian (Headless or Headful). Now I just need to figure out how to purchase the full version, as there is no hint on their site of how to do so.

1 comment:

  1. Hi
    I am glade to see you are able to successfully running Java SE for Embedded 6.0 on SheevaPlug.
    I am new to SheevaPlug. Do I have to build Java SE for Embedded 6.0 on SheevaPlug after downloading it? or just un-tar an use it?
    I am using PogoPlug that has 128MB RAM. If I have to compile it , please let me know the instructions.
    Thanks
    Sam

    ReplyDelete