Making The Chumby function with a Shared Dictionary

Demos.Chumby History

Hide minor edits - Show changes to output

Changed lines 273-274 from:
Here is the relevant file ( Attach:crossdomain.txt remain crossdomain.xml ). Note that this file MUST be placed in the root directory of the website, or it will not work, and the Chumby will be unable to access the page.
to:
Here is the relevant file ( Attach:crossdomain.txt rename crossdomain.xml ). Note that this file MUST be placed in the root directory of the website, or it will not work, and the Chumby will be unable to access the page.
Changed lines 273-274 from:
Here is the relevant file ( Attach:crossdomain.xml ). Note that this file MUST be placed in the root directory of the website, or it will not work, and the Chumby will be unable to access the page.
to:
Here is the relevant file ( Attach:crossdomain.txt remain crossdomain.xml ). Note that this file MUST be placed in the root directory of the website, or it will not work, and the Chumby will be unable to access the page.
Changed lines 273-274 from:
Here is the relevant file. Note that this file MUST be placed in the root directory of the website, or it will not work, and the Chumby will be unable to access the page.
to:
Here is the relevant file ( Attach:crossdomain.xml ). Note that this file MUST be placed in the root directory of the website, or it will not work, and the Chumby will be unable to access the page.
Added lines 97-128:
Similarly, we update a text file

public bool Upload(string newMessage)
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] textBytes = encoding.GetBytes(newMessage);

string uri = "ftp://" + ftpServer + "/" + "uploadedText.txt";
FtpWebRequest reqFTP;

reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
reqFTP.UseBinary = true;
reqFTP.ContentLength = textBytes.Length;
try
{
Stream strm = reqFTP.GetRequestStream();
strm.Write(textBytes, 0, textBytes.Length);
strm.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Upload Error");
return false;
}
return true;
}

As an example, here is a C# program ( Attach:SDFTPUploader.zip ) that takes webcam photos and puts them into a shared dictionary. When the shared dictionary is updated, it uploads the photo to the ftp site, and updates a textfile with an increasing number.
Changed lines 131-138 from:
Attach:SDFTPUploader.zip
to:
Usage:

1
. Upon opening this program, the EasyImages webcam server will launch. Start the camera server.
2. In the main program window, press "Connect" and connect to the shared dictionary.
3. enter your ftp server and login data and press "log on"

Every 30 seconds the ftp server should be updated with a new image and a updated text file.
Added line 99:
Attach:SDFTPUploader.zip
Changed lines 97-98 from:
Attach:ftp-client.jpg
to:
Attach:FTP-client.jpg
Added lines 97-98:
Attach:ftp-client.jpg
Changed lines 223-224 from:
That's all there is to displaying an image on The Chumby. There is a more sophisticated way to do this so that no flickering occurs, This is explained [[http://wiki.chumby.com/mediawiki/index.php/Sample_Webcam_Widget | here.]]
to:
That's all there is to displaying an image on The Chumby. You'll notice that it may flicker slightly when the image refreshes. There is a more sophisticated way to do this so that no flickering occurs, This is explained [[http://wiki.chumby.com/mediawiki/index.php/Sample_Webcam_Widget | here.]]
Changed lines 197-198 from:
Simply start a new project as we did before and enter this code into the Action window.
to:
Simply start a new project. In the Action window, enter this code.
Changed line 201 from:
createEmptyMovieClip("image",0); // We'll just create all the components through flash. This is a EmptyMovieClip called "image"
to:
createEmptyMovieClip("image",0); // We'll just create all the components through action script. This is a EmptyMovieClip called "image"
Changed lines 218-219 from:
Which looks like this:
to:
Go to "Control" and select "Test the Movie." You should get a window that looks like this:
Added lines 218-222:
Which looks like this:

Attach:flash12.jpg
Changed lines 197-198 from:
Simply start a new project and enter this code into the Action window.
to:
Simply start a new project as we did before and enter this code into the Action window.
Changed lines 200-201 from:
delay = 1000; // one second refresh rate
createEmptyMovieClip("image",0); // We'll just create all the components through flash
to:
delay = 5000; // one second refresh rate
createEmptyMovieClip("image",0); // We'll just create all the components through flash. This is a EmptyMovieClip called "image"
Changed lines 211-214 from:
//
// rotate the images, load the next one
//
to:
// Load the image
Changed line 213 from:
var movie = eval("image");
to:
var movie = eval("image"); // load up the MovieClip we've called "image"
Added lines 218-219:
That's all there is to displaying an image on The Chumby. There is a more sophisticated way to do this so that no flickering occurs, This is explained [[http://wiki.chumby.com/mediawiki/index.php/Sample_Webcam_Widget | here.]]
Changed line 154 from:
[=
to:
Changed line 174 from:
=]
to:
Changed lines 198-199 from:
[=
url = "@@http://pages.cpsc.ucalgary.ca/~saul/wiki/uploads/Main/saul-photo.jpg@@"; // link to the cam feed
to:
url = [= "http://pages.cpsc.ucalgary.ca/~saul/wiki/uploads/Main/saul-photo.jpg" =]; // link to the cam feed
Changed line 211 from:
=]
to:
Changed line 154 from:
to:
[=
Changed line 174 from:
to:
=]
Changed line 198 from:
to:
[=
Changed line 211 from:
to:
=]
Changed line 199 from:
url = "http://pages.cpsc.ucalgary.ca/~saul/wiki/uploads/Main/saul-photo.jpg"; // link to the cam feed
to:
url = "@@http://pages.cpsc.ucalgary.ca/~saul/wiki/uploads/Main/saul-photo.jpg@@"; // link to the cam feed
Added lines 197-220:
Simply start a new project and enter this code into the Action window.

url = "http://pages.cpsc.ucalgary.ca/~saul/wiki/uploads/Main/saul-photo.jpg"; // link to the cam feed
delay = 1000; // one second refresh rate
createEmptyMovieClip("image",0); // We'll just create all the components through flash
//
then = 0; // set the last time we loaded the image to a really long time ago.
this.onEnterFrame = function () {
now = (new Date()).getTime(); // get current time in milliseconds
if (now-then>delay) { // enough time elapsed since last image loaded?
doLoadImage(); // load the image
then = now; // and reset the last load time
}
}

//
// rotate the images, load the next one
//
function doLoadImage() {
var movie = eval("image");
movie.loadMovie(url); // load image into it
}
Added lines 193-196:
!! Displaying an image in Flash

In our C# example, we showed capturing images and displaying them on the web. This example is slightly different from our last example. It can be done simply in action script.
Deleted lines 210-214:
When programming in Flash CS3, you will have to always “Save As…” and select Flash 8, because flash will not, by default, save a Flash 8 file. It will overwrite that file with a CS3 Flash file. Ensure that you test the movie after it has been saved as an Flash 8 file as well, to generate the proper SWF file.


(section on setting up the flash program)
Deleted lines 157-158:
Deleted line 166:
Deleted line 167:
Deleted lines 170-171:
Deleted lines 174-175:
Changed lines 110-111 from:
We'll start by creating a flash program that reads a website. It's available here, but i've also written a tutorial. Anyway, open Flash CS3.
to:
We'll start by creating a flash program that reads a website. It's available here ( Attach:text.fla ), but i've also written a tutorial. Anyway, open Flash CS3.
Changed lines 110-111 from:
We'll start by creating a flash program that reads a website. Open Flash CS3.
to:
We'll start by creating a flash program that reads a website. It's available here, but i've also written a tutorial. Anyway, open Flash CS3.
Changed line 155 from:
url = "http://google.com"; // link to the text
to:
url = "http://grouplab.cpsc.ucalgary.ca"; // link to the text
Changed lines 158-164 from:
//
// onEnterFrame-based loading
//
// We aren't using setInterval/clearInterval to avoid
// potential memory/timer leaks in the Flash player
//
then = 0; // long, long ago....
to:

// Start this function on load
then = 0; // set the initial time
Changed lines 163-164 from:
now = (new Date()).getTime(); // get current time in ms from the epoch
if (now-then>delay) { // enough
time elapsed since last image loaded?
to:
now = (new Date()).getTime(); // get current time in milliseconds
if (now-then>delay) { // enough time elapsed since last
time loaded?
Added line 182:
Deleted lines 150-151:
Changed lines 185-186 from:
to:
7. Saving that document

Attach:flash9.jpg

We're done so we might as well save. Remember to save the program as a Flash 8 file, or nothing will work. Every time you save, Flash will try to save it as a CS3 file. You'll have to "Save As..." each time.

8. Generate the .SWF file

You'll need to generate a flash movie.

Attach:flash10.jpg

Goto control and select Test Movie

Assuming everything works, you'll see a window trying to display the Grouplab homepage's text.

Attach:flash11.jpg
Changed lines 157-173 from:
url = "http://google.com"; // link to the text
delay = 1000; // one second refresh rate
ourLabel.text = "";


//
// onEnterFrame-based loading
//
// We aren't using setInterval/clearInterval to avoid
// potential memory/timer leaks in the Flash player
//
then = 0; // long, long ago....
this.onEnterFrame = function () {
now = (new Date()).getTime(); // get current time in ms from the epoch
if (now-then>delay) { // enough time elapsed since last image loaded?
doLoadText(); // request text
then = now; // and reset the last load time
to:
url = "http://google.com"; // link to the text
delay = 1000; // one second refresh rate
ourLabel.text = "";
//
// onEnterFrame-based loading
//
// We aren't using setInterval/clearInterval to avoid
// potential memory/timer leaks in the Flash player
//
then = 0; // long, long ago....
this.onEnterFrame = function () {
now = (new Date()).getTime(); // get current time in ms from the epoch
if (now-then>delay) { // enough time elapsed since last image loaded?
doLoadText(); // request text
then = now; // and reset the last load time
}
Changed lines 174-188 from:
}

var lv:LoadVars = new LoadVars();

lv.onData = function(thetext:String) {
ourLabel.text = thetext;
}


function doLoadText() {
lv.load(url);
}
to:
var lv:LoadVars = new LoadVars();

lv.onData = function(thetext:String) {
ourLabel.text = thetext;
}


function doLoadText() {
lv.load(url);
}
Added line 189:
Changed lines 145-146 from:
Attach:flash6.jpg
to:
Attach:flash7.jpg
Changed lines 149-150 from:
6.
to:
6. Action window



Unselect everything. We now need to open up the actions window, and add some action script to make everything actually work. Here's the code that I added:

Attach:flash8.jpg

url = "http://google.com"; // link to the text
delay = 1000; // one second refresh rate
ourLabel.text = "";


//
// onEnterFrame-based loading
//
// We aren't using setInterval/clearInterval to avoid
// potential memory/timer leaks in the Flash player
//
then = 0; // long, long ago....
this.onEnterFrame = function () {
now = (new Date()).getTime(); // get current time in ms from the epoch
if (now-then>delay) { // enough time elapsed since last image loaded?
doLoadText(); // request text
then = now; // and reset the last load time
}
}

var lv:LoadVars = new LoadVars();

lv.onData = function(thetext:String) {
ourLabel.text = thetext;
}


function doLoadText() {
lv.load(url);
}
Changed lines 134-135 from:
Open up components and drag it onto the document
to:
Open up components and drag a label object onto the document
Added lines 138-150:
5. Setting the label properties/parameters

Attach:flash6.jpg

Open up the properties for the label. We need to give the object a name. I've named it "ourLabel".
To make it a text field as large as the Chumby screen, I've set the location to x = 0, y = 0, and its dimensions to 320x240.

Attach:flash6.jpg

Just for fun, under the parameters, and make the label an HTML label. It'll ignore tags that way.

6.
Changed lines 130-131 from:
4. Getting a label
to:
4. Adding a label to the document
Added lines 134-137:
Open up components and drag it onto the document

Attach:flash5.jpg
Added lines 128-133:
For this tutorial, I'll assume that you know how to have Flash display the Actions, Properties, Parameters, and Components windows. I keep them by the side of the workspace because I use them a lot.

4. Getting a label

Attach:flash4.jpg
Changed lines 114-115 from:
Attach:Flash1.jpg
to:
Attach:flash1.jpg
Changed lines 118-119 from:
Attach:Flash2.jpg
to:
Attach:flash2.jpg
Changed lines 122-123 from:
Attach:Flash3.jpg
to:
Attach:flash3.jpg
Changed lines 126-127 from:
Attach:Flash2a.jpg
to:
Attach:flash2a.jpg
Changed lines 122-123 from:
to:
Attach:Flash3.jpg

3. Setting up your Flash environment

Attach:Flash2a.jpg
Added lines 108-125:
!! Text

We'll start by creating a flash program that reads a website. Open Flash CS3.

1. Begin by creating a new Flash 2.0 program

Attach:Flash1.jpg

2. We now need to set up the document so that it can be displayed on a chumby

Attach:Flash2.jpg

The dimensions should be set at 320 pixels by 240 pixels. The frame rate should be set at 12 fps.



!! Getting the values on the Chumby
Added line 71:
// Takes an EasyImages JPEG object and uploads it to the server
Changed line 93 from:
return true;
to:
return true; //upload successful!
Changed line 74 from:
string uri = "ftp://" + ftpServer + "/" + "uploadedImage.jpg";
to:
string uri = "ftp://" + ftpServer + "/" + "uploadedImage.jpg"; //Turn the server location into a full path
Changed lines 76-86 from:
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
reqFTP.UseBinary = true;
reqFTP.ContentLength = imageBytes.Length;

int buffLength = 2048;
byte[] buff = new byte[buffLength];
to:
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); // create a new instance of an FtpWebRequest
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); //THe id/password for log in
reqFTP.KeepAlive = false; //Terminate after file uploads
reqFTP.Method = WebRequestMethods.Ftp.UploadFile; //You want to upload a file
reqFTP.UseBinary = true; //Transfer is binary
reqFTP.ContentLength = imageBytes.Length; //How long is the file?
Added line 85:
strm.Write(imageBytes, 0, imageBytes.Length); //send a file of imageBytes.Length to the server
Changed lines 90-91 from:
MessageBox.Show(ex.Message, "Upload Error");
return false;
to:
return false; //upload failed
Changed lines 59-60 from:
A class for connecting to an FTP server:
to:
A simple class for connecting to an FTP server and replacing a file called @@webserver.com/uploadedimage.jpeg@@ :
Deleted lines 89-97:



// for (int i = 0; i < imageBytes.Length; i++)
// {
// strm.wr
strm.Write(imageBytes, 0, imageBytes.Length);
// strm.WriteByte(imageBytes[i]);
// }
Changed line 61 from:
@@public class ftpUpdater
to:
public class ftpUpdater
Changed lines 108-109 from:
}@@
to:
}
Changed line 61 from:
@@ public class ftpUpdater
to:
@@public class ftpUpdater
Added lines 59-109:
A class for connecting to an FTP server:

@@ public class ftpUpdater
{
string ftpServer, ftpUserID, ftpPassword;
public ftpUpdater(string newFtpServer, string newFtpUserID, string newFtpPassword)
{
ftpServer = newFtpServer;
ftpUserID = newFtpUserID;
ftpPassword = newFtpPassword;
}

public bool Upload(EasyImages.JPEG image)
{
byte[] imageBytes = image.GetByteArray();
string uri = "ftp://" + ftpServer + "/" + "uploadedImage.jpg";
FtpWebRequest reqFTP;

reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
reqFTP.UseBinary = true;
reqFTP.ContentLength = imageBytes.Length;

int buffLength = 2048;
byte[] buff = new byte[buffLength];

try
{
Stream strm = reqFTP.GetRequestStream();



// for (int i = 0; i < imageBytes.Length; i++)
// {
// strm.wr
strm.Write(imageBytes, 0, imageBytes.Length);
// strm.WriteByte(imageBytes[i]);
// }
strm.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Upload Error");
return false;
}
return true;
}
}@@
Changed lines 11-12 from:
The Chumby is a small inexpeinsive device capable of displaying a/v data. It is also an input device able to capture user interaction through a touch screen and a accelerometer. For these reasons, the Chumby can be called a “data appliance” or, in the terminology at Grouplab an Ambient Device. In this article, we show how to send messages and data to and from the Chumby and a Shared Dictionary.
to:
The Chumby is a small inexpensive device capable of displaying a/v data. It is also an input device able to capture user interaction through a touch screen and a accelerometer. For these reasons, the Chumby can be called a “data appliance” or, in the terminology at Grouplab an Ambient Device. In this article, we show how to send messages and data to and from the Chumby and a Shared Dictionary.
Changed lines 29-30 from:
to:
!!! Overview
Changed lines 52-53 from:
to:
!!! Shared Dictionary to Web
Changed lines 64-65 from:
to:
!!! Web to Chumby
Added line 48:
Added lines 50-61:
[[#SDtoWeb]]


Language: C#

This stage of the project is basically a traditional shared dictionary project. We will create a small program that connects to a shared dictionary and updates a file on a webpage via ftp. The file that we will update can be an image, an mp3, an html file, or raw text.


>><<


>>greybox<<
Added lines 44-45:
Attach:webdiagram1.jpg
Added lines 64-65:
Attach:Chumby.jpg
Added lines 66-68:

(section on setting up the flash program)
Changed lines 99-101 from:
7. Once this is finished.
to:
7. Once this is finished you can close your webbrowser and pick up the Chumby.

(insert chumby walk through if this thing ever works again)
Changed lines 88-89 from:
5.
to:
5. Go and select "Manage Channel" I've previously made an extra channel called "SaulStuff". This is the one I will manage.
Added lines 91-96:

6. Go to the category you uploaded the widget to, select it, and choose "ADD WIDGET"

Attach:ChumbyWeb5.jpg

7. Once this is finished.
Added lines 80-90:
Remember the category that you uploaded the widget as. Also, ensure that you uploaded it as "private" unless you want others downloading your widget.

Attach:ChumbyWeb2.jpg

4. After uploading, it, move over to "My Chumby" and select "my chumby dashboard"

Attach:ChumbyWeb3.jpg

5.

Attach:ChumbyWeb4.jpg
Changed lines 74-75 from:
[[Attach:ChumbyWeb1.jpg]]
to:
Attach:ChumbyWeb1.jpg

3. Fill in the details

Note: You will need a 80x60 jpeg as a thumbnail for that widget. I've provided one [[Attach:chumbo.jpg | here
]].
Changed lines 74-75 from:
[[attach:ChumbyWeb1.jpg]]
to:
[[Attach:ChumbyWeb1.jpg]]
Changed lines 74-75 from:
@ChumbyWeb1.jpg
to:
[[attach:ChumbyWeb1.jpg]]
Added lines 68-75:
Here is a step by step guide to uploading a widget:

1. Login to Chumby.com

2. Mouse over "Widgets" and select "Submit a widget"

@ChumbyWeb1.jpg
Added lines 44-67:
>><<

>>greybox<<
[[#WebtoChumby]]


Language: Flash Lite 3.0

Having placed the value(s) on a website in part one, we now need to get them off and onto the Chumby.

Here we encounter our first serious “Gotcha” – the Flash Security Settings.

Flash, by default, will not allow an application to access data on another website. Certain data types seem to be freely parsed (like jpegs), while others, like html, Flash needs permission to display. The permission is not a setting from within Flash. Instead, the permission must be given by the webserver.

Here is the relevant file. Note that this file MUST be placed in the root directory of the website, or it will not work, and the Chumby will be unable to access the page.

If you looked at the file, you will have noticed that the permission is given to Chumby.com. This is because all of the chumby communications go through that website.

This may lead to some unexpected behavior. I’ve seen a chumby not update it’s display despite numerous pings on the webserver from the chumby.com.

When programming in Flash CS3, you will have to always “Save As…” and select Flash 8, because flash will not, by default, save a Flash 8 file. It will overwrite that file with a CS3 Flash file. Ensure that you test the movie after it has been saved as an Flash 8 file as well, to generate the proper SWF file.

Once written, getting a widget on the Chumby is also somewhat tricky.
Added lines 25-43:
>><<

>>greybox<<
[[#Overview]]

The Chumby is a Linux based, wi-fi capable microcomputer. By default, it only runs small widgets, which are small Flash programs and movies. These movies are arranged into “channels”. Channels are collections of movies set up so that every x-number of seconds (by default 15) the device changes to display changes to the next script. This allows the chumby to, overtime, display a wide variety of small bits of data. These could be news headlines, webcam images, or sounds. After each script in the channel has been displayed, it begins again, at the start of the list.

The Linux core of the device has made it popular for hacking. Various people have written Chumby web servers, Chumby mp3 plays, and so forth. While the chumby is quite limited in terms of memory and processor power, the 2 USB ports on the back allows for additional memory or devices to be added to it.

Such properties potentially make the Chumby very attractive for prototyping domestic and ubiquitous computing applications. In a project that Kathryn and I worked on in 2006/2007 (see Location Aware Devices for the Home), we wanted a small, digital display device that could display flickr albums associated with a particular location. To this end, an excellent use of the Chumby would be to extend it to recognize and interact with phidgets and augment it with an RFID reader. By connecting the Chumby to a shared dictionary, it would have satisfied all our needs.

Extending the OS or functionality is outside of the scope of this small set of tutorials. We will use the device as it arrives out of the box. The goal is to show how it could be used in conjunction with Groups Lab’s Shared Dictionary, a component of the .Networking package. This is not always an easy task, and will require working in several programming languages. It will also require having unfettered access to a webserver.

For the purpose of this project, we will assume familiarity with C# and the .networking package. We will not assume any familiarity with Flash/Actionscript or PHP.

The difficulty comes from Flash. While current versions of Flash/Actionscript are less limited, the version of flash we will be able to use is extremely limited. The Chumby comes installed with Flash Lite 3.0, a simplified form of Flash 8.

In Flash 8, there are very limited methods available for inter-process communication. IPC is never easy, but here we are constrained solely to accessing webpages. That is, all data, including updates from the Shared Dictionary, that are transferred into or out of a Chumby, must be send through a webpage.
Added lines 20-24:

And, maybe eventually:

*[[#ChumbytoWeb | Part Three: Chumby to Web]]
*[[#WebtoSD | Part Four: Web to SD]]
Added lines 1-20:
(:title Making The Chumby function with a Shared Dictionary :)
%define=box padding-left=1em padding-right=1em margin='3px 3px 0'%
%define=yellowbox box bgcolor=#fdfaea border='1px solid #ffad80'%
%define=redbox box bgcolor=#fff3f3 border='1px solid #ffc9c9'%
%define=bluebox box bgcolor=#f4fbff border='1px solid #a1cae6'%
%define=skybox box bgcolor=#f8fcff border='1px solid #aaaaaa'%
%define=greybox box bgcolor=#fbfbfb border='1px solid #aaaaaa'%
%define=greenbox box bgcolor=#e6f3e5 border='1px solid #8fd586'%
%define=whitebox box bgcolor=#ffffff border='1px solid #999999'%

The Chumby is a small inexpeinsive device capable of displaying a/v data. It is also an input device able to capture user interaction through a touch screen and a accelerometer. For these reasons, the Chumby can be called a “data appliance” or, in the terminology at Grouplab an Ambient Device. In this article, we show how to send messages and data to and from the Chumby and a Shared Dictionary.

THIS PAGE IS UNDER CONSTRUCTION!!!

>>greybox<<
!!! Contents
*[[#Overview| Overview]]
*[[#SDtoWeb| Part One: Shared Dictionary to the Web]]
*[[#WebtoChumby | Part Two: Web to Chumby]]
>><<