At long last, Chumby is now available in the United States. While it remains to be seen whether Chumby reaches the status of an iPod or a Pet Rock, mobile developers in North America can use this device as a platform to build Flash Lite applications with unprecedented ease.
Chumby is the first commercial Flash Lite 3 device available in the US, supporting both ActionScript 2.0 and FLV video files encoded with the On2 codec. The Chumby has a blazing 350 MHz processor and a whopping 64 Megs of RAM—allowing developers to build Flash Lite 3 applications without the same pesky performance limitations usually encountered when developing apps for mobile devices.
Flash developers should find Chumby interesting because it runs Flash applications (called widgets). Chumby users can use these widgets to search the Internet, monitor RSS feeds, check eBay auctions, display webcams, watch video and gather information that is normally accessed via a desktop computer. Since Chumby supports Flash and ActionScript 2.0 developers are creating their own widgets to achieve a wide range of personal goals—such as controlling a home media server, adding items to a grocery shopping list, or sending alerts when a message is received on twitter.com.
The Chumby device is unique. If it was simply an "always-on" Internet-connected device with a small color screen, it would be hard to separate it from those digital photo frames that are popular among grandparents. Instead of a hard plastic frame, the outside of a Chumby is soft and squishy, making it irresistibly fun to squeeze its bean bag-like texture. It has a touch screen, too. But best of all, its motion-sensing accelerometer allows you to calculate its current orientation and the amount of agitation being applied to the device.
In this article I'll show you how to begin building Flash widgets for Chumby, by creating a project that connects to Chumby's accelerometer. For the purposes of this article, I'll focus on working with Flash-based widgets that you manually install or distribute publicly through chumby.com.
Specifically, I'll describe the basics of Flash Lite development and highlight some of the new features available in Flash Lite 3. I'll also cover how to work within the security restrictions inherent in hosting your application on another domain. I'll provide some suggestions for optimizing your applications to run on Chumby's processor and show you how to tap into Chumby's built-in accelerometer using ActionScript.
It is important to note that the Chumby device is very open to hacking. The Chumby team has published the motherboard's schematic, and they even provide documentation on how to overwrite the Chumby operating system. There are many things you can do with a Chumby; you can even create a new leather cover. The topics of customizing a Chumby and hacking the OS are outside the scope of this article, but if you are interested in learning more, I encourage you to search online where you'll find many tutorials and ideas.
To make the most of this article, you'll need the following software and files:
Prior experience developing with Flash is advised, but this article is geared towards anyone interested in an overview of creating Flash widgets for the Chumby device.
Depending on your prior development experience, Flash Lite 3 will either seem like a step back (if you are more familiar with ActionScript 3.0) or a giant leap forward (if you are more familiar with the pre-ActionScript 2.0 used in Flash Lite 1.x). I think of Flash Lite 3 as Flash Player 7 (using ActionScript 2.0) with just a few limitations described below. However, Flash Lite 3 does support the newer On2 video codec (in addition to the Sorenson Spark codec), so you could also say Flash Lite 3 is similar to Flash Player 8 without some of the features (most notably blend effects and filters). It all depends on how you look at it.
The following list of Flash Player 8 desktop features are not supported when developing Flash Lite 3 projects for the Chumby:
Additionally, there are other features that probably don't apply anyway, such as using LocalConnection and various System.capabilities properties.
The list above is not all-inclusive, but it does provide a good starting point of things to consider when designing your widget. To see a complete list, check out the unsupported and partially supported ActionScript elements section in the Flash Lite 3 online documentation.
Here's all you need to do to prepare a Flash file to develop a Chumby widget.
Select Modify > Document from the main menu. In the Document Properties dialog box, set the stage dimensions to 320 × 240 pixels and set the frame rate to 12 (see Figure 1).

Figure 1. Set the stage dimensions to 320 × 240 and ensure that the frame rate is set to 12 fps
Select File > Publish Settings. In the Flash tab, use the version drop-down menu to select Flash Lite 3.0. By making this selection, you ensure that the movie's ActionScript version is set to ActionScript 2.0. Additionally, this setting causes Adobe Device Central to launch whenever you select Control > Test Movie (see Figure 2).

Figure 2 . Choose Flash Lite 3.0 from the version drop-down menu in the Publish Settings dialog box
If you haven't already, be sure to download and install the recent update for Flash CS3 Professional. If you haven't yet installed it, you won't be able to select Flash Lite 3.0 from the version drop-down menu in the Publish Settings dialog box.
Also, be sure to check out the Chumby profile for Device Central created by Scott Janousek. You can download and install the profile to see your project emulated in Device Central using the Chumby specifications.
The main purpose of setting the version to Flash Lite 3.0 is to ensure you receive warnings about any unsupported functionality you might attempt to use when you publish the movie. Additionally, when you use this setting, various unsupported features (such as blend modes and line cap styles) will be disabled as you edit the file in the Flash CS3 authoring environment.
You have two options for installing and running a widget on your Chumby:
Option 1: Manually copy the SWF file (along with the equivalent of an "autostart" text file) to your Chumby device using a USB thumb drive
Option 2: Publish the SWF file to the developer portal at chumby.com. This option involves a completing the form on the Upload Widget page (see Figure 3).

Figure 3. You can upload your widget on chumby.com to distribute it to Chumby devices
It's well worth the extra effort to publish your widget on chumby.com, because doing so allows you to make your widget publicly available to all the consumers who own a Chumby. The users who own a Chumby use the site to set up channels and choose which widgets to run on their device. A channel can feature just one widget or it can be set to automatically cycle through multiple widgets.
It may sound counter-intuitive, but even as I'm in the testing phase, I like to publish my widgets to chumby.com (instead of copying the SWF file directly to my device via the USB port). In my experience, I find it's actually faster to upload a replacement SWF file to chumby.com and refresh my Chumby, in comparison to copying the files to a thumb drive and then restarting the Chumby to apply the changes.
Here's the testing cycle workflow that I use:
It is only necessary to perform the steps listed above once. However, after you've revised your widget and you're ready to test the updated version on your device, follow these steps:
To learn more about how users find and share your widgets, visit chumby.com. These steps are provided in order to show you the minimum steps required to publish and update your widgets using chumby.com.
When your widget plays on a user's Chumby device, it's effectively loaded (via a loadMovie command) into a shell movie. Both the shell and your widget are downloaded from chumby.com to the device. This is important information if you plan on developing functionality that allows your widget to load data, images, sounds, or other SWF files from other domains—even from your own domain. Flash Player has built-in security restrictions preventing cross-domain access. If the SWF file you've developed originates on chumby.com, as all published widgets do, then your SWF file can only draw data directly from chumby.com. Luckily, there is a wealth of information available online about how this works and various strategies for loading external data. To get an overview of the security model included in Flash Player and how to use crossdomain.xml permission files, check out the Developer Connection article: Creating more secure SWF web applications.
Basically, if you want to provide dynamic data (such as tracking a shipped package or displaying the local weather forecast) then your widget must first have permission to access the domain where that data is provided. If you run a server that provides the data, you can simply copy a crossdomain.xml file to the root level of your server. If the source of the data resides on another domain (and that domain doesn't already have a crossdomain.xml file) then you'll need to set up a proxy server to allow your widget to call your server (still, with permission granted via the crossdomain.xml file) and then set up your proxy server to retrieve the data from the other domain and return it to the widget.
During the process of publishing your widget, you have an option to include a "configuration widget". This is a SWF file that can only be accessed by the end users at chumby.com via the "customize" link that appears with every widget that they add to their channel. If you don't create a configuration widget, the customize option only allows the users to specify how long a particular widget plays before cycling to the next widget on the channel. However, if you include a configuration widget, it serves as the UI to let users save data similar to storing a cookie or working with a local shared object. For example, if you create a weather checking widget, it would be helpful to provide a field where the end user can enter their zip code.
Including a configuration widget has two benefits. First, it offers you the ability to build a UI that's not limited by Chumby's small touch screen, because users access and enter their information into the customize page (the configuration widget) while using their browser—with their mouse and keyboard. Second, if you include the configuration widget, you can leverage it to save variables for each user between sessions. This offers a convenient strategy to allow each specific user to save their settings and the saved variables are automatically loaded the next time your widget runs on their device.
The process of writing the variables to chumby.com from a configuration widget is a bit tricky, and I'll cover that in a minute. However, each variable the user saves to a configuration widget is set automatically, the same way FlashVars work. The good news is that when your Chumby widget loads, those variables are already set and accessible.
To create a configuration widget, I recommend starting with the sample provided on the Chumby Wiki. If you check out the code on Frame 1 of the file named simplebanner_config.fla, you'll see all kinds of gnarly ActionScript, but the key section of the code is provided below:
function gotParameters(x) {
_root.params = x;
gotoAndStop(2);
}
Basically,
the function above sets all of the variables that were previously saved into a
variable named params. It may seem odd to start the widget
running with the values that used to be, but understand that all except
first-time users are returning to the configuration widget. Your application
will be more inviting to users if you can display their current settings.
We'll
continue evaluating the code of the configuration widget by examining the code
on Frame 2. Here the text field is populated with the value of params.banner with the following line of code:
bannerInput.text = _root.params['banner']
In this
configuration widget, the only variable that is saved is called banner ,
but it is possible to save more than one entry item. In order to support
multiple variables, banner is saved as a property of the object params .
For this reason, the variable is actually params.banner .
After the
user clicks Done, you can see (inside the done() function) that the value of the
text field is saved back into the params.banner variable and the value is saved in
chumby.com's databases via the _chumby_set_widget_parameters() function (which is located in
the code on Frame 1). Finally, the configuration widget calls a JavaScript
function called dismiss() which is part of the page that
hosts the configuration widget at chumby.com.
If you want
to learn more, you can download the configuration widget and deconstruct the
code, but it works…so I recommend simply changing the graphics on Frame 1 and
then replacing the contents of the Stage on Frame 2 while continuing to use the params object to access the parameter(s) you
plan to use.
For example,
if you want to save a user's city and state, you can replace the content on the
Stage at Frame 2 with two input text fields (city_txt and state_txt ) and a button instance named doneButton . Then replace the ActionScript in Frame 2 with this
code:
city_txt.text = params.city;
state_txt.text = params.state;
doneButton.onRelease = function() {
params.city = city_txt.text;
params.state = state_txt.text;
_chumby_set_widget_parameters(doQuit,params);
}
function doQuit() {
_chumby_exit();
}
It's
important to remember that the values you save can only be strings or numbers.
If you want to store an array, for example, you'll need to come up with a
strategy such as using join() before saving the values and
then split() when restoring them.
The most
convenient thing about using configuration widgets is that once the data is
saved, your actual Chumby widget receives those variables automatically when it
starts up (for example city , state or banner) .
However, be sure to account for the possibility that these have a value of undefined (which will occur for all new users that have not yet
run your configuration widget).
While it's a fairly powerful Flash Lite 3.0 device, the Chumby's processor is very slow compared to a typical desktop computer. I equate it with an old Pentium-era computer. The harsh reality is that your Flash widget can quickly eat up its share of the available 32 MB of RAM. If nothing else, developing Flash applications for the Chumby will cause you to consider every available option to optimize your code, to seek out and follow best practices. This process can influence the development strategies you follow in the future, making your regular apps even more efficient.
The message of this section is simple: be conservative. When adding animated content, be super creative as you decide how to communicate your ideas. In other words, step back and consider the minimum message you're attempting to convey. Instead of using a 20-frame tween to display a bouncing ball, create a similar effect using a few carefully crafted keyframes. There are many old tricks that you can borrow from traditional animation to improve performance on devices. Another way to design conservatively is to think about the impression you want to make, not the actual physics behind the movement.
For example, imagine you want to animate a bird in flight. It is more important to animate the impression the movement makes on you (free flight, fluttering, changing course) than showing the true physics (the wing formation, aerodynamics, and so on). Of course, in a perfect world you'd use long, smooth alpha tweens with bounce effects, but remember that your animations will not look very good if the SWF file chokes due to performance issues.
When I first began developing for the Chumby, it was a real wake up call for me. The prototype Chumby had only 16 MB of RAM. I created some really cool widgets, and they worked great when I tested them on my desktop. But it was an eye opener when I deployed them to the Chumby. All of the available RAM was quickly consumed and the Chumby restarted.
The bottom
line here is to clean up after yourself in your code. Don't leave any variables
hanging around that you don't need. Use the
delete myVariable
command whenever you're done with a variable. Also, be sure to call clearInterval() for every setInterval() you start to conserve resources.
Traditionally, programmers advise that you worry about optimization later in a development project, but when you are developing Chumby widgets I think it helps to adopt an efficiency-minded approach from the very start. For more tips, be sure to check out the performance tips provided in the Chumby Wiki.
Finally,
there are a few other design considerations to keep in mind. For one thing, you
can't call the Mouse.show() functions because the cursor never appears. Similarly,
it's best to forget about creating any rollover effects. Making the
user drag their finger on the touch screen is questionable—so use
"flicking" features with discretion. The good news is that while the
Chumby hardware imposes some restrictions, it also opens up a very interesting
opportunity, to access the built-in accelerometer. In the next section, I'll
describe how to connect to Chumby's accelerometer using ActionScript.
A Chumby widget is really just a SWF file that runs in the context of the Chumby framework. Developing Flash widgets for the Chumby is an interesting proposition, because Flash Lite imposes a few restrictions, your widget resides on chumby.com, and the modest processor in the Chumby tempers your appetite for special effects. The reason I find developing for the Chumby unique and fun is the ease with which you can access the accelerometer that senses the device's orientation and how much it's being shaken.
When people encounter the Chumby, the first thing they do is pick it up—after all, it looks like a bean bag. Devising creative ways to take advantage of the ability to access a Chumby's orientation is really interesting. Imagine a music player that switches genres when the user whacks the side of Chumby. Or, create a magic 8 ball widget (I previously created this app, but I'm sure you could improve upon it).
In the next section, I'll show you how to grab the values sent from the accelerometer to use in your Flash widget. The process is a bit geeky (after all, Flash Lite 3.0 doesn't have built-in support for this). The trickiest part involves understanding what the values really mean. There are values for X, Y, and Z orientation, but unlike 3D software (where × and Y are left/right and up/down and Z is depth) Chumby's accelerometer doesn't report the location in space where the Chumby resides. Rather, the three values (X, Y, and Z) reflect how the three faces of the device (side, top, and front) are currently positioned.
Imagine that the Chumby is a cube, like a single die (see Figure 4).

Figure 4. It helps to think of the Chumby as a cube when reviewing the values provided by the accelerometer
The touch screen on the front of the Chumby is on the same plane as the number 3 on the die. Consider that the range of positions (for the front face of the Chumby) varies from facing straight up (if you're holding the Chumby in your lap and you look down at the screen) to facing straight down (if you're holding the Chumby up above your head looking up at the screen). The "normal" position (as shown in the figure above) is really in the middle of that range. Of course, if you consider a full rotation there are actually two versions of "normal"—one with the screen right side up and one with the screen upside down. However, these positions are both vertical. The accelerometer simply reports the proportional position between a maximum value for face up to a minimum value for face down. The accelerometer reports the front face's position (between face down and face up) as the Y. It reports the side (where the 2 on the die appears) as the X. And it reports the top face (the 6 on the die) as the Z.
The range of motion for the × position from a maximum value (the side is facing up) to its mid-point (the side is vertical) to the minimum value (the side is facing down) is illustrated in the diagram below (see Figure 5).

Figure 5. The accelerometer provides values based on the range of motion from pointing straight up to pointing straight down
The same system is used for all three faces. (In case you're pondering the fact that a cube really has 6 faces, just think of it as 3 pairs where each face has a partner on the opposite side that is always in direct proportional orientation.)
You can use
ActionScript to access the values sent from the accelerometer through an undocumented
function: ASnative(5, 60) . You just need to add a line of
code:
var getAccelerometer:Function = ["ASnative"](5, 60);
Next, you can
set up an onEnterFrame event to repeatedly ascertain the
accelerometer's values—such as getAccelerometer(). To specify which of the X, Y, or
Z values you wish to access, you pass a single numeric parameter to the
function. For example, to grab the current × orientation, you'd call getAccelerometer(2). The following chart outlines the
values you can access and the corresponding parameter to use:
version = _accelerometer(0); timestamp = _accelerometer(1); currentX = _accelerometer(2); currentY = _accelerometer(3); currentZ = _accelerometer(4); avgX = _accelerometer(5); avgY = _accelerometer(6); avgZ = _accelerometer(7); impactX = _accelerometer(8); impactY = _accelerometer(9); impactZ = _accelerometer(10); impactTime = _accelerometer(11);
There are a
few items I want to point out about using these parameters in your code. Since the
values for avgX, avgY , and avgY are
averages of the last few readings, they yield smoother results than the
otherwise identical values currentX , currentY ,
and currentZ .
The impact
values let you sense how hard—and in which direction—the user last whacked the
Chumby. Since you'll need to query the accelerometer to read any of these
values, it is important to realize that the impact readings are from the last
impact felt. You can use impactTime to ensure that the impact is a new impact (not one you already reacted to) before displaying a graphic or an
animation.
Finally, it
is important to note that the units used for all these readings can seem odd.
The orientation values (currentX , currentY , avgX , avgY , and avgZ )
range from a minimum of about 1200 to a maximum of 2800… putting the midpoint
at 2000 (indicating that the corresponding face is vertical). The values for
impact range from 0 to 4095. A value of 0 is the maximum force if you hit one
pane, while 4095 is the maximum if you hit the opposite pane (or, I suppose you
could think of it as "pulling" the same pane). Anyway, an absence of
force is not 0 but the midpoint value—namely, 2048. The total range maps from
-5G to +5G. When you multiply any of the impact readings by
0.0024489559928062587 and then subtract 5, you'll get a value that ranges from
-5 to 5. In my experience developing for the Chumby, there are no magic
settings. You really just have to tweak the impact values until your widget
"feels" right.
I created a
utility class that is designed to insulate you from having to deal with the
details of using Chumby's accelerometer. The main feature of this class is the
ability to listen for three events: onImpact,
onRotation , and onOrientation . These events are only fired when an impact occurs, the
rotation changes by more than 1 degree, or when the orientation changes (in
order to rotate the display like the iPhone).
In the next
section I'll review the code in the provided sample file that uses these three
event listeners, but the key (besides not having to directly access the
accelerometer yourself) is that since the events only fire when a change
occurs, it is not necessary to update the graphics onscreen for every onEnterFrame event. Doing so could cause your widget to perform
poorly. The utility class includes an event called onUpdate that broadcasts all the accelerometer readings 12 times a second, and you can
create an event listener for onUpdate if that is helpful when developing
your widget project.
If you haven't already, download the sample file provided on the first page of this article . Open the FLA file in Flash CS3 Professional so you can evaluate it as I walk through the process I used to create it. Using the com.phillipkerman.chumby.utils.Accelerometer class is fairly straightforward.
//create instance:
myAccelerometer = new com.phillipkerman.chumby.utils.Accelerometer();
//set up listeners
myAccelerometer.addEventListener("onImpact", chumbyImpact);
myAccelerometer.addEventListener("onOrientation", chumbyOrientationChange);
myAccelerometer.addEventListener("onRotation", chumbyRotate);
//kick start it
myAccelerometer.init();
You really
don't have to subscribe to all these events. For example, if you only want to
listen for the onOrientation event, you can remove the other two
lines with the addEventListener methods.
Finally,
without going into the details of the Accelerometer class I wrote, let me
explain up front that all these listenable events send a property that I
created called rawValues . This is an object with properties
for each of Chumby's accelerometer readings (version, timestamp, currentX and so on) plus g-force adjusted values I created (impactX_normal, impactY_normal , and impactX_normal )
as well as offX and offY —which
I used to create the bubble-level effect. In addition, the onOrientation event sends a value for the orientation (strings "north", "east",
"west", or "south ") and the onRotation event sends a value for the
Below I've provided my handlers for the three listenable events:
function chumbyImpact( evt ){
shake_mc.play();
var values:com.phillipkerman.chumby.datatypes.RawValues = evt.rawValues;
shake_mc._x = CENTER_X + (values.impactX_normal / 1000) * (STAGE_WIDTH);
shake_mc._y = CENTER_Y + (values.impactY_normal / 1000) * (STAGE_HEIGHT);
}
The main thing to note above is how I dampen the (g-force adjusted) impact values (by dividing by 1000) and move the shake_mc clip. That movie clip contains a rough animation which, when complete, also restores the clip's original location.
function chumbyOrientationChange( evt ){
switch ( evt.orientation ){
case "north":
orientation_mc._rotation = 0;
break;
case "east":
orientation_mc._rotation = 90;
break;
case "west":
orientation_mc._rotation = 270;
break;
case "south":
orientation_mc._rotation = 180;
break;
}
}
The code above simply flips the orientation_mc clip to display so that it's always facing up. You could certainly add some fancy animation to tween this change.
function chumbyRotate ( evt ){
level_mc._rotation = evt.angle / (Math.PI/180);
var values:com.phillipkerman.chumby.datatypes.RawValues = evt.rawValues;
bubble_mc._x = CENTER_X - values.offX * CENTER_X;
bubble_mc._y = CENTER_Y - values.offY * CENTER_Y;
}
The level_mc simply rotates to match the angle—though the value needs to be converted to degrees first, before rotation. The bubble_mc (the crosshairs) is a bit odd. To see it, you need to hold the Chumby with the screen horizontal and look down at it. Alternately, you can also see the crosshairs if you hold the Chumby directly above your head and look up.
At this point you have the technical details necessary to build a widget for your Chumby. You can also share your widget with other users through chumby.com. Now the only remaining thing to do is come up with an interesting idea for a widget you want to build. I recommend browsing the widgets already available on chumby.com to get some inspiration.
Developing for Chumby offers a "fun factor" that just isn't available in the more typical web applications. The fact that your Chumby can reside in any room of your house means you can create all sorts of new applications. And for me, the fact that you can create something truly tangible using the built-in accelerometer opens up a whole new universe of user input. I really think the Chumby framework offers an exciting new playground for Flash artists, developers, and animators.
To research in more depth, check out these online resources:
Phillip Kerman is a teacher, writer, and programmer focusing on the Adobe Flash platform. He's programmed several games on MSN and Messenger Live including Sudoku Too and Jigsaw Too. He also programmed the real-time cattle auction site stampedecattle.com. Recently his focus is on cashing-in before Bubble 2.0.