Dashboard Confessional

When Panic, a Mac software development firm with a strong flair for visual design, showed their scratch built digital dashboard I felt an overpowering urge to make one for myself. To avoid having to pay $3,000 for the wall-mounted monitor, I built it with a RSS-reading wireless digital photo frame. I got it done for $150 and 2 days of work. The code is open source so that you can make yourself one, too.

Here's just the dashboard itself:

Show/hide Table of Contents






Why Build A Dashboard?

I'm a longstanding fan of having a dashboard built into one's website for monitoring, analytics, and customer service purposes, but the reasons to have one publicly visible are different. For Panic, it probably achieves an espirit de corps and lets them quickly communicate project status. For a single-man "team" like my company, it gives me:

  • Motivation to continue working on projects.
  • Non-urgent status notifications without turning on the computer.
  • Obviously visible signs of progress.

Back to the Table of Contents





Overall Architecture

I'm using a wireless digital photo frame which is capable of displaying RSS picture feeds. An implementation detail with the particular model of photo frame I have is that those feeds have to go through Windows Live FrameIt, which was a source of plenty of frustration to me for reasons which will be made clear shortly.

There are a million ways to generate pictures. Since I happen to run a business which does PDF creation and that hammer makes me see nails everywhere, I used to lay out text and graphics, and then to convert the PDFs to images.

The actual generation of the stats is done on my server, with Rails. In addition to pulling some values from the database, I also did a bit of work with modern web technologies like RSS and web services, partially for practical utility and partially to show how you can do it. Since some of the statistics are expensive to calculate or fetch, I elected to do it asychronously via Delayed::Job. This could just as easily be done with a cron task on a repeating timer.

Back to the Table of Contents





Materials List

Here's exactly what I'm using:

  • Buffalo PF-50WG Wireless Digital Photo Frame (I got mine from Amazon Japan)
  • Windows Live FrameIt (free), required by the frame to wrap my RSS feed.
  • Prawn for PDF generation (the easiest way to lay out images I know)
  • GraphicsMagick for converting PDFs to images
  • SimpleRSS to parse RSS feeds for data for the frame
  • Delayed Job
  • Ruby on Rails (tying everything together)

In addition, I had a beautiful set of education icons from IconShock lying around, so I used them for some visual flair. (They'd run about $100 if purchased solely for this project.)

Back to the Table of Contents





What To Display

I didn't want the photo frame to just repeat what I can tell from a glance at my web-based dashboard. Also, while I could use it for failure monitoring, the Ride of the Valkyries ringtone that gets triggered on my cellphone is much more attention-grabbing. I wanted something that fits in with my lifestyle: an understated reminder of work remaining to be done, for when I'm not on the computer.

The dashboard currently shows:

  • A count of unread emails (total and support-related) from Google Apps.
  • Sales statistics (for the current month, year, and the percentage growth and forecast)
  • A guilt-trip feature: time passed since last release, A/B test released, and blog article written.
  • A quick one-glance business health check.
  • Titles from recent emails.
  • Tweets, because I know the first question folks would ask is "Can you put Twitter on it!?". Heaven knows how we wasted time before Twitter.

Back to the Table of Contents





Issues In Development

This project took about three times as long as it should have:

Windows FrameIt is an abomination.The photo frame presumably has limited onboard processing, so to avoid having to be compatible with any random RSS feed, it passes them through Windows FrameIt, a Microsoft SAAS offering which is essentially "input an RSS feed, get an RSS feed in a specified format". However, Windows FrameIt is a terrible piece of software from the perspective of a developer -- the error messages are totally opaque (try {... } catch(Exception) { System.out.println("This feed had no images in it.");} and compatibility with published RSS specs is spotty. I eventually got it working by copying my Flickr feed and migrating each XML element to the form needed by the dashboard. You wouldn't think a dashboard would need a photographer attribution, but apparently Windows FrameIt it won't run without it.

PNG incompatibility. I didn't realize until late in the project that the photo frame cannot use PNGs, despite Windows FrameIt helpfully coercing them into (unreadable) JPGs for it. This ate a few hours discovering and then tweaking so that the JPGification process didn't result in ugliness.

Generic hackiness. Laying out anything as an image will always be harder and probably uglier than doing the same operating in HTML/CSS. However, it means that you don't need a browser (and machine capable of running one) for the display, so I pressed on.

Back to the Table of Contents





OSS Dashboard Code

This code is not productized -- you'll have to do significant modifications to make it useful for your needs (for example, coding the actual logic to calculate your own statistics.)

This code is available under the MIT license, just like Rails. Please feel free to modify it to suit your purposes, use it as a springboard, or extend and commercialize it. If you'd rather read it in your IDE, click the little icon in the top-right corner to copy/paste.

We'll begin with the controller, which defines one action for the RSS, one for serving images, and one for serving image thumbnails.

Show/hide code for dashboard_controller.rb

Almost all the heavy lifting -- including data access, calculations, and PDF generation -- is performed by the model. You'll likely rewrite most of this. All display-oriented code is in the pdf method and below.

Show/hide code in dashboard.rb

The view for the RSS feed is absurdly fragile, at least if you're using Microsoft FrameIt. You can mostly copy/paste it. Note this also supports Google Reader, Firefox, and other RSS readers for testing.

Show/hide code in dashboard.rb

Finally, there are the entries in routes.rb. Since this system has no security whatsoever (not that it needs it -- aside from the email headers all the information is public) I put a big random string in the URLs to sort of deter prying eyes.
You'll note the :id in the RSS feed URL. That just lets me change the physical URL on a whim, which was important in development because Microsoft perma-cached the content of early versions frequently and would not update at the speed I was developing at.

  map.dashboardRSS '/security-through-obscurity/:id/:format.xml', :controller => 'dashboard', :action => 'rss'
  map.dashboardImage '/security-through-obscurity/:timestamp.:format', :controller => 'dashboard', :action => 'image'
  map.dashboardImageThumbnail '/security-through-obscurity/dashboard-thumbnail.:format', :controller => 'dashboard', :action => 'thumbnail_image'
  

There is also some magic done in my nginx config. This is used for the nginx file serving performed by the controller. Strictly speaking this URL doesn't have to be internal, but I wanted to force all access through Rails.

  location /dashboard-internal/ {
      internal;
      root /var/www/apps/DailyBingoCards/shared/storage;
      expires 5M;
      rewrite ([^\/]*)$ /dashboard/$1 break;
  }
  

Back to the Table of Contents





Further Refinements

There are a few obvious ways you could improve this system. I might implement some of them in the future.

  • Swap the image template used each interval, allowing the dashboard to display more stuff, in bigger font, in a more engaging manner.
  • Include sales graphs, server monitoring graphs, etc created in Gruff.
  • Make the design pretty. As you can probably tell, I am not a much-beloved Mac software design house.

Back to the Table of Contents





Conclusion

I hope you enjoyed this article. If you have a dashboard, I'm always interested in seeing what other people are doing, for inspiration. Shoot me an email at patrick@this-domain or feel free to tweet at @patio11. Your comment will, of course, show up on my dashboard.

Please pass this article to anyone you think will benefit from it.