Thursday, March 31, 2011

Federation Clock v0.1 Error

Technorati Tags: ,,

Well my last entry showed how I created an analog clock using ActionScript. This seemed to work well and I was rather pleased with it. On the Chumby I I set the default run time to 15 seconds so that was the longest that I had it running. The other day I decided to pin the widget which leaves it running continuously. When I came back to the Chumby after an hour or so passed, I noticed the hands were missing from my clock. I then ran it on the PC and let it run for awhile and sure enough the hands of the clock started separating. Below are some images over a 6 minute interval.

ClockError0ClockError1ClockError2ClockError3ClockError4ClockError5

I tried several things to fix it such as resetting the top left point and not calculating the rotation point and just using (160, 120) but these did not help. I really don’t know what is going on here so if you do, please help me out and post a comment with a suggestion. The only thing I can think of trying is removing the MovieClip object and adding it back again but I assume this will take more processing time and is quite wasteful. There must be a better way.

Tuesday, March 29, 2011

Developing for the Chumby - Federation Clock v0.1

Technorati Tags: ,,

FederationClock

I had been trying to learn ActionScript and figured the best place to start was to create a simple analog clock but found it very frustrating. Most of the examples for analog clocks are in fla format which requires Adobe tools to create and cost quite a bit. I sometimes question why Chumby Industries went with Flash when they are so focused on providing Open Source products. After much frustration I was able to get the job done and it came out quite nicely. Hopefully someone will find this example useful and save them some frustration.

BTW: I am impressed that there really is not much code to write to get this to work. Most of my frustration came with trying to get the hands of the clock to rotate about a point other than (0, 0). One would think that Adobe would have made it so you could set a registration point on an object but they did not for some reason. They did provide the matrix class which allows you to transform an object to get the same effect.

Source code for this project is at http://www.teelsys.com/Chumby/Clock_0_1.zip.

Project Files

FederationClock001First let’s take a look at the files in the project.

The bin folder contains the compiled swf file. The library folder contains the images used to create the clock. The FederationClock.jpg file is the background of the clock. The other three image files are the hands of the clock. Notice that the color of the files in the FlashDevelop Project Explorer are blue color verses the FederationAnalogClock.jpg file in the root of the project. The blue color indicates that they are part of the assembly and will be included in the final assembly (swf file).

The src folder contains the util folder which contains source files which are included with Chumby project template. The src folder also contains the Main.as which has the main code for the project and will be discussed below.

Finally the FederationAnalogClock.jpg file is a 80x60 thumbnail image to be used when adding the widget to the Chumby either through the Chumby website or on a USB flash drive.

Main.as

FYI: I got some ideas and source code from various sources and have included those in the comments of the source code.

I am sure that this code can be improved greatly and I have some ideas on ways that it can be improved. I have commented on some things which can be improved and I may incorporate those changes at a later time. The biggest improvement that can be made to this code is to create a new class which extends the MovieClip class and adds a registration point to allow the MovieClip to rotate around a point other than (0, 0). This would allow this code to be applied to many more things beyond a simple clock.

Variable Declarations

The first thing I need to comment about is that the key words for private, public, and static must be used differently in ActionScript than in other languages or I am not seeing something with how they are used. I had an issue with the Point types as the values were lost between function calls unless I used the static keyword. I will need to look into the scope of ActionScript variables a bit more so I can understand what the differences are and why I needed to use the static keyword.

private var parent:MovieClip;
private var clockBackground:MovieClip;
private var hourHand:MovieClip;
private var minuteHand:MovieClip;
private var secondHand:MovieClip;
static var hourRotatePoint:Point;
static var minuteRotatePoint:Point;
static var secondRotatePoint:Point;
static var hourCurrentAngle:Number;
static var minuteCurrentAngle:Number;
static var secondCurrentAngle:Number;

There are three basic groupings for the variables. The first are the MovieClip variables for the background and the hands of the clock. The second group are the Point variables for holding the registration points of the clock hands and the last group are number variables for recording the current angle of the hands.


init()

The init function is used to place the background and the clock hands in the widget as well as initializing the registration points and the current angle of the clock hands. Finally the init function calls the clock_onEnterFrame so the clock will show the current time on start.

function init()
{
// Add images to the app
clockBackground = parent.attachMovie("library.FederationClock.jpg", "clockBackground", parent.getNextHighestDepth());
hourHand = parent.attachMovie("library.hourHand_mc.png", "hourHand", parent.getNextHighestDepth());
minuteHand = parent.attachMovie("library.minuteHand_mc.png", "minuteHand", parent.getNextHighestDepth());
secondHand = parent.attachMovie("library.secondhand_mc.png", "secondHand", parent.getNextHighestDepth());

// Position the hands to 12:00:00 position
hourHand._x = (Stage.width - hourHand._width)/2;
hourHand._y = (Stage.height/2) + 8 - hourHand._height;
minuteHand._x = (Stage.width - minuteHand._width)/2;
minuteHand._y = (Stage.height/2) + 8 - minuteHand._height;
secondHand._x = (Stage.width - secondHand._width)/2;
secondHand._y = (Stage.height / 2) + 35 - secondHand._height;

// Pin Location (Registration Point)
hourRotatePoint = new Point(hourHand._x + (hourHand._width/2), hourHand._y + 86);
minuteRotatePoint = new Point(minuteHand._x + (minuteHand._width/2), minuteHand._y + 113);
secondRotatePoint = new flash.geom.Point(secondHand._x + (secondHand._width/2), secondHand._y + 107);

hourCurrentAngle = 0;
minuteCurrentAngle = 0;
secondCurrentAngle = 0;

// Show the current time
clock_onEnterFrame();
}

rotateAroundPoint

The rotateAroundPoint function rotates a MovieClip around the registration point by a number of degrees. One thing to remember is if the MovieClip is already rotated, it will be rotated from the current position so the final angle will be the current rotation plus the angle passed into the function. I had not thought of this and when my code started working it produced an interesting effect with the seconds going faster and faster.


I want to thank Ryan Bosinger for posting this code on his blog. It helped a great deal although I could not get it to work at first. The reason it was not working is the scope of the variables as I mentioned above.

// FROM: http://ryanbosinger.com/blog/2008/actionscript-30-rotate-around-center-point/
static function rotateAroundPoint (mc:MovieClip, angleDegrees:Number, ptRotationPoint:Point)
{
var m:Matrix=mc.transform.matrix;
m.tx -= ptRotationPoint.x;
m.ty -= ptRotationPoint.y;
m.rotate (angleDegrees*(Math.PI/180));
m.tx += ptRotationPoint.x;
m.ty += ptRotationPoint.y;
mc.transform.matrix = m;
}

Main

The Main function is the constructor for the Main class. I just took the default name for the class and I think this makes things a bit confusing as I had thought this function was the starting point of the application however it is not.


The Main function initializes the parent variable, runs the init function, and assigns the onEnterFrame event handler for the parent MovieClip. (OK, I don’t know why I am assigning it using the mc variable rather than the parent variable. They are the same instance so it works.)

function Main(mc:MovieClip)
{
// save reference to main movieclip
this.parent = mc;

init();

mc.onEnterFrame = clock_onEnterFrame;
}

onMenuSelect

Dead code which was from the Chumby project template.

function onMenuSelect(i:Number) {
trace("select " + i);
}

main

The entry point for the application.

static function main(mc:MovieClip)
{
var app = new Main(mc);
}

clock_onEnterFrame


The clock_onEnterFrame function is the event handler which handles the onEnterFrame event. This is the function which drives the application.


The function gets the current time and determines how many degrees each of the hands should be at in order to display the time. To reduce some processing time, the angle required to display the time is compared to the current angle of the hand. If they are the same then the rotation code is not called. The frame rate for the project is 12 fps so I assume this is called 12 times per second. I suppose it may be more efficient to change the frame rate for the project to 1 fps.


If the angles are different then the hand is rotated back to the original position then moved to the correct angle. I am sure there is a better way to do this so if you do it differently please comment on it.

function clock_onEnterFrame()  {
var dt:Date = new Date();
var hrs:Number = dt.getHours() + dt.getMinutes() / 60 + dt.getSeconds() / 3600;
var mns:Number = dt.getMinutes() + dt.getSeconds() / 60;
var scs:Number = dt.getSeconds();

//set hour hand
var angle:Number = hrs * 30;
if (angle != hourCurrentAngle)
{
rotateAroundPoint(hourHand, -hourCurrentAngle, hourRotatePoint);
rotateAroundPoint(hourHand, angle, hourRotatePoint);
hourCurrentAngle = angle;
}

//set minute hand
angle = mns*6;
if (angle != minuteCurrentAngle)
{
rotateAroundPoint(minuteHand, -minuteCurrentAngle, minuteRotatePoint);
rotateAroundPoint(minuteHand, angle, minuteRotatePoint);
minuteCurrentAngle = angle;
}

//set second hand
angle = scs * 6;
if (angle != secondCurrentAngle)
{
rotateAroundPoint(secondHand, -secondCurrentAngle, secondRotatePoint);
rotateAroundPoint(secondHand, angle, secondRotatePoint);
secondCurrentAngle = angle;
}
}

Conclusion


I hope you have found this useful. Please if you have any ideas or comments on this code, please post them below.


If you look for this clock on the Chumby site you will not see it there. I felt there are too many clocks to choose from and this one is no different and no better than the others listed on the site. I have some ideas to create a clock which utilizes the built-in alarm clock and/or shows world times. If I do create something more useful along those lines, I will add them.


You are free to modify the code presented here to create your own clock. Have fun and post any comments you may have regarding this code or any other posts on this blog.

Wednesday, March 16, 2011

Chumby Screen Capture

Technorati Tags: ,

Where you wondering how I captured the screen shots from the Chumby for my previous post? I found some information on how to view the Chumby screen on the PC. The method is straight forward but is not easy to remember and requires refreshing of the browser window to see what is currently on the Chumby. To solve this problem, I wrote a few HTML pages to solve the problem.

The information on how to capture the screens is posted at Chumby tricks – Chumby Wiki.

Prepare your Chumby

In order to view the Chumby on your PC, you need to do a couple of things on the Chumby itself.

  • Obtain the IP Address of the Chumby.
    • From the Control Panel select Settings
      00ControlPanel
    • From the Settings Screen, select “Chumby info”
      01Settings
    • Take note of the IP Address on the screen. (Write it down you will need it later!)
      0109ChumbyInfoIP
  • Turn on
    • From the Chumby Info screen, you will see a little “pi” symbol in the upper right corner. Touch it.
      02ChumbyInfo
    • You will see a screen with some buttons. Click the “FBCGI” button.
      0110PiButtons
      FYI: Nothing will change on the screen.

 

Using the HTML Project

  • Download the HTML files from http://www.teelsys.com/Chumby/MyChumby.zip.
  • Unzip the files to a convenient location such as your desktop
  • View the index.htm file in your browser
    NOTE: Tested on Google Chrome 10, IE 8, Safari 5, and Firefox 3.6.8. It ran fine on all of these browsers but failed to run properly on the Archos 70 tablet.
    0100ScreenCapture
  • Enter the IP Address of your Chumby in the text box and click the “GO” button.
    0101ScreenCapture
  • You should now see the Chumby screen in one of the windows on the page. The page will refresh every 15 seconds to show the current image.
    0108ScreenCapture
  • If you wish to change the refresh rate, view the included ReadMe.txt file.

Developing for the Chumby

Technorati Tags:

I just bought a Chumby One and of course I have to learn how to write a widget for it. I was getting a bit frustrated with not finding a complete step by step guide. I was able to find information from various places and put it all together to figure out how to write these Flash Widgets. To make matters a bit more complicated, I do not own, nor have access to any of the Adobe editors so I needed a freeware solution. This does limit you when it comes to the examples posted online as many of them are in fla file format which is of no use unless you have an Adobe Flash editor.

Environment

I am running Windows 7 (64 bit) so if you are on a Mac or Linux this may be of little use. I may try to create widgets in Ubuntu at some point. If I do, I will add a similar post.

You will need the following software installed before going into the Hello World example.

  • FlashDevelop is an open source editor for ActionScript 2 & 3.1
  • Flash Player 10.1 ActiveX runtime (required by the browser control) 2
  • Java 1.6 runtime (JRE) (required if using the Flex SDK) Flex SDK Download 2
  • Chumby Template for FlashDevelop by Raff 2 Follow the directions in the readme file as to where to copy the files.
  • A SSH Client such as PuTTY. PuTTY is a free Telnet/SSH Client for Windows.

 

Hello World

Once the environment is setup the next thing is to create a Hello World application to help become familiar with the development process. I found a very good example at http://wiki.chumby.com/mediawiki/index.php/FlashDevelop/Example. There are a few things which are not spelled out and caused me a bit of a problem. The following instructions are copied from the site. I have made a few modifications and added some screen shots.

Prerequisites 3

I made the mistake of not paying attention to these and later when told to use SSH, I connected a USB Hub to the Chumby and connected the thumbdrive and a keyboard. Everything was fine until I attempted to run the application. It was also very difficult to read the text on the small screen.

Create a New Project 3

  • Start FlashDevelop
  • Click on Project –> New Project
    05FlashDevelopNewProject
  • Select the ActionScript2 –> Chumby project template
    NOTE: If the Chumby Project is not shown then you did not copy Raff’s template in the correct location.
    06FlashDevelopChumbyProject
  • Give this project a name "Hello World", and check the "create directory for project" check box.

This will give you a Project pane on the right side, with bin and src folders. 07FlashDevelopIDE

Write Your Program 3

  • Open the Main.as file, located in the src folder, on in the right pane
  • Write the Hello world program as follows:
    class Main
    {
    public static function main():Void
    {
    _root.createTextField("t",2,20,20,100,30);
    _root.t.text = "Hello, world!";
    }
    }

Test your program in FlashDevelop 3

  • Click on Project->Test Movie (or F5)
  • A new page will open with your Hello World program running. Note the "Hello World.swf" tab. You have just created your first swf file!
    08TestFlashDevelop

Test your program on your Chumby 3 

  • Copy the HelloWorld.swf file from the bin folder to the root of the flash drive then plug the flash drive into your Chumby
  • Open the SSH Client such as PuTTY to connect to the Chumby
    09PuTTY
  • Once connected, login as root. Note, there is no password for the root account.
    10PuTTYWindow
  • Once you are logged in, you will see the Chumby Mascot
    11LoggedIn
  • Stop the current Chumby flash player
    chumby:~# stop_control_panel
    *** stopping control panel
    *** killing registered flashplayer pid: 1821
    Adobe FlashLite 3.1.7 Release (Version 9,1,122,0)- Chumby Industries (version 9 build 115-3412 [GCC 4.3.2])
    Portions copyright (C) 2005-2010 Chumby Industries, Inc.
    Built for: falconwing; Features: Video ALSA ARM-optimizations
    Build time: Wed 29Sep2010 1833
    chumbyflashplayer.x: sending signal 15 (SIGTERM) to running instance 1821
    chumbyflashplayer.x: retry #1, signalling process 1821 again
    chumbyflashplayer.x: registered instance 1821 appears to have terminated
    btplay client v1.4.1.38.50
    Connected to btplayd instance 1820
    Got response: OK 100 quit
    Matched request 100
    Waiting 500ms for process to terminate
    Continuing...
    *** killing btplayd (SIGTERM): 24335
    *** killing btplayd (SIGKILL): 24335
    chumby:~#
    

  • Run your program
    chumby:~# chumbyflashplayer.x -i /mnt/usb/HelloWorld.swf
    Adobe FlashLite 3.1.7 Release (Version 9,1,122,0)- Chumby Industries (version 9 build 115-3412 [GCC 4.3.2])
    Portions copyright (C) 2005-2010 Chumby Industries, Inc.
    Built for: falconwing; Features: Video ALSA ARM-optimizations
    Build time: Wed 29Sep2010 1833
    2011-03-17 00:06:16 OpenSoundOutputSync(): shm_open(/aplaypipe-shm) failed errno=2 (No such file or directory)Playback device is default
    Stream parameters are 44100Hz, S16_LE, 2 channels
    2011-03-17 00:06:16 TRACE: preload.swf v1.02
    2011-03-17 00:06:16 BtPlayObject::StartBtplay() - LaunchDaemon() call response timed out
    2011-03-17 00:06:16 ChumbyPipeObject::FindByRequest(103) failed - no find amongst 2 entries!
    ...

  • Confirm your program is running on your chumby!
    12RunningOnChumby
  • Use ctrl-C to exit the player.
    ^C2011-03-17 00:06:19 chumbySignalHandler(2) SIGINT - requested termination
    2011-03-17 00:06:20 ChumbyVidStats::RuntimeCleanup(): 0 sessions started, 0 cancelled, originating pid=24967, last reporting pid=0
    2011-03-17 00:06:20 chumbySignalHandler(13) SIGPIPE received, new count = 1
    2011-03-17 00:06:20 err[11]: 2011-03-17 00:06:19 chumbySignalHandler(2) SIGINT - requested termination
    
    2011-03-17 00:06:20 err[12]: 2011-03-17 00:06:20 chumbySignalHandler(13) SIGPIPE received, new count = 1
    
    2011-03-17 00:06:20 Exiting _chumby_flashplayer_version=317.9.00115-3412
    2011-03-17 00:06:20 Start time: 2011-03-17 00:06:16
    2011-03-17 00:06:20 End time  : 2011-03-17 00:06:20
    2011-03-17 00:06:20 Elapsed   : 4s (4)
    2011-03-17 00:06:20 main() - closing and deleting pid file /var/run/chumbyflashplayer.pid
    2011-03-17 00:06:20 chumbyflashplayer main() - exiting, return code 0
    chumby:~#

  • Restart your Chumby to restore to normal operations OR to restart Chumby flashplayer:-
    chumby:~# start_control_panel
    --00:10:49--  http://www.chumby.com/crossdomain.xml
    => `/dev/null'
    Resolving www.chumby.com... 69.43.206.45
    Connecting to www.chumby.com|69.43.206.45|:80... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 272 [application/xml]
    
    100%[====================================>] 272           --.--K/s
    
    00:10:49 (1.66 MB/s) - `/dev/null' saved [272/272]
    
    imgtool 1.22 (built for falconwing)
    Filling with r,g,b 0,0,0 (0x00000000)
    Opening output /dev/fb0 fmt=0
    fb handle = 3
    Filled with 0x0, no image to load, exiting
    imgtool 1.22 (built for falconwing)
    Filling with r,g,b 0,0,0 (0x00000000)
    Opening output /dev/fb1 fmt=1
    fb handle = 3
    Filled with 0x0, no image to load, exiting
    Starting btplay daemon
    Adobe FlashLite 3.1.7 Release (Version 9,1,122,0)- Chumby Industries (version 9 build 115-3412 [GCC 4.3.2])
    Portions copyright (C) 2005-2010 Chumby Industries, Inc.
    Built for: falconwing; Features: Video ALSA ARM-optimizations
    ...

Alternate Testing on your Chumby 4

  • Create a jpg thumbnail for your widget. The thumbnail should be 80 pixels wide and 80 pixels high. Name your image “HelloWorld.jpg”.
     HelloWorld
  • Create a file named profile.xml and paste the following contents. You may edit this file in case your assembly or thumbnail file are named differently or you wish to name your widget something else.
    <profile>
    <widget_instances>
    <widget_instance id="1">
    <name>Hello World</name>
    <widget>
    <name>Hello World</name>
    <description>This is my Hello World widget</description>
    <version>1.0</version>
    <mode time="10" mode="timeout"/>
    <access sendable="false" deleteable="false" access="private" virtualable="false"/>
    <user username="myusername"/>
    <thumbnail href="file:////mnt/usb/HelloWorld.jpg" contenttype="image/jpeg"/>
    <movie href="file:////mnt/usb/HelloWorld.swf" contenttype="application/x-shockwave-flash"/>
    </widget>
    <access access="private"/>
    <mode time="5" mode="timeout"/>
    <widget_parameters>
    <widget_parameter>
    <name>zipcode</name>
    <value>90210</value>
    </widget_parameter>
    <widget_parameter>
    <name>phonenumber</name>
    <value>867-5309</value>
    </widget_parameter>
    </widget_parameters>
    </widget_instance>
    </widget_instances>
    </profile>

  • Copy the three files to the root of the thumbdrive
    • HelloWorld.jpg
    • HelloWorld.swf
    • profile.xml

  • Reboot the Chumby with the USB Thumbdrive still attached

References

  1. FlashDevelop - ChumbyWiki, http://wiki.chumby.com/mediawiki/index.php/FlashDevelop
  2. Installation – FlashDevelop, http://www.flashdevelop.org/wikidocs/index.php?title=Installation
  3. FlashDevelop/Example – ChumbyWiki, http://wiki.chumby.com/mediawiki/index.php/FlashDevelop/Example
  4. Chumby tricks – ChumbyWiki, http://wiki.chumby.com/mediawiki/index.php/Chumby_tricks#Mixing_local_widgets_into_a_channel