Contact Info

(for those who care)

Instant Gratification   

Tue, 26 Apr 2016

Writing my First Watchface for Pebble

For the longest time I’ve had an idea for a binary clock that’s easier to read than the traditional “powers of two” ones you’ll find at the nerd stores.

The design I came up with has some inspirations from a very old linux desktop gizmo I believe from the GNUStep era. I don’t remember the name of that little clock app but I think I’ve done enough refinement and design to claim this design as my own.

You’ll see in the image below that “X” is located at the traditional “12:00” position on an analog clock and “Y” is located just before the “6:00” position (meaning it’s indicating “5:00”. This setup makes it easy to see at a glance what the hour hour is and while “binary” is really much closer to the hour hands of an analog clock.


    . . X . X . .  
    . . . . . . . 
  / . . . . . . . \
 9  . . . . . . .  3
  \ . . . . . . . /
    . . . . . . . 
    . . . . Y . Y 


Now the question is how to indicate minutes? Following a similar line of reasoning, you start counting from zero at the 12:00 position down towards the middle in groups of five. It works out that you can fit a full “minute hand” that grows inwards from the edges and covers all 60 minutes contained in an hour.

  . . X 1 X . .    . . X . X . .  
  . . . 2|. . .    . . . . . . . 
  . . . 3V. . .    . . .35 . . . 
  . . . 4 . . .    . . .34 . . . 
  . . . 5 . . .    . . .33^. . . 
  . . . . . . .    . . .32|. . . 
  . . . . . . .    . . .31 . . . 

My experiences working with the Pebble SDK

It has been a long time since I’ve written C code, but the SDK has good documentation, quick start guides and examples to build from.

Memory management hasn’t been too much of an issue since the trend for watchfaces seems to be “assume you’re the only thing running, and don’t be too afraid of global variables”. The code isn’t something I’d be proud of if I were shipping this as a library or if I were a professional C programmer, but so far it seems to work well enough.

Using C, pointers, static initializers, etc. really makes me appreciate dynamic languages a lot more and efforts around modernizing low-level languages that you see with Rust and others. It’s so convenient to have sane initializers, data access, iterators, and parameter passing for programmer comfort even though it can compile down to the same bytecode or instruction sequence. With raw C it seems like it’s always a struggle to factor out some code into a function call, much more so than in a dynamic language.

Making a “Professional” Watchface

I didn’t want to just build a static watch face. Once I got the basics working, I wanted to experiment with having a settings panel at least to flip between having a light background or dark background.

The settings infrastructure is honestly a weak point of the Pebble SDK. Each watchface can have an app.js which triggers a simple Pebble.openURL( 'http://...' ). You have access to basically a full web browser for users to configure the watchface but there were several problems I had working with it.

The basic demo configuration was OK and a good starting point, but I’d love a pebble new-config "KEY_FOO=toggle, KEY_BAR=color, KEY_BAZ=radio(1,2,3)". As it is now, there’s a lot of copying/pasting and trying to find examples that makes things more difficult.

Even better would be to have some sort of Pebble.js included or injected automatically so that you can simply say: Pebble.fetch( { "KEY_FOO": function() { ... }, "KEY_BAR": "#key_bar.value" } ); … handle the common cases easily and avoid as much code duplication as possible, especially on the frontend.

Also I don’t like that you have to have the configuration page hosted somewhere on the internet. Tying watchface configuration to public URLs will lead to watchface decay as developer domain names expire, heroku accounts get abandoned, etc.

I’ve experimented with using modern browser Blob and createObjectURL API’s to bundle the whole config page into the *.pbw itself, but it gets tricky to dynamically integrate that with the full build process. It’s an awful lot of somewhat risky work to be done to replace something that’s working fine right now so I’ve currently punted on investing programming time in that.

Areas for Improvement

It’d be great to have a set of open source modules for building watch faces, pebble grab-lib weather-access, or pebble grab-lib bluetooth-loss-vibrate. It’d be much more convenient to have some infrastructure in place to help raise the bar as to what users expect a watchface to have and to be pleasantly surprised when more watchfaces support more features.

Overall I’m very happy with the development process. It was fun to have a fast iteration cycle and to literally see the changes happening on my wrist as I was making changes to bitmasks and graphics calls. There was an immediacy around controlling a physical object through code that pebble has really nailed in their developer experience, and this doesn’t even begin to cover the fantastic CloudSDK or JS watchfaces.

The results of this work has gotten me featured in the “Brain Teaser” category of watchfaces and at least a few installs. It’s been a really fun process and has gotten me searching for cheap Pebble Time watches on Craigslist so I can experiment with color, hopefully pick up even more users and installs.

12:37 CST | category / entries
permanent link | comments?

Like what you just read? Subscribe to a syndicated feed of my weblog, brought to you by the wonders of RSS.

Thanks for Visiting!