Thursday, June 22, 2017

Android Wear's WatchMaker: A Hacker's Delight

A Little Kvetching, A Little Inspiration

My ZenWatch 3 came with an impressive number of watch faces pre-installed. And many of them look quite cool. But alas, that's also the problem: they just look cool. On my list of needs from a smart watch, aesthetics is near the bottom while functionality and hackability are at the top.

While pondering this dearth of appealing watch faces it hit me, why don't I build my own? I make use of Tasker and AutoWear to expand my watch's capabilities, perhaps I can do the same thing with a custom built watch face?

I hit Google and found various articles that talked about getting into the custom watch face game. This article recommended WatchMaker, which seemed like a good fit. While WatchMaker has a massive gallery of watches, you can also build your own. Without having a clue, I created a blank watch face and started clicking around. As I browsed hrough the list of elements I could add to my creation I noticed the option of adding an 'Expression':

Clicking on this option took me to list of various types of data I could add, such as the time or weather information. As I scrolled down further I saw there was Tasker support (whoo!) and ultimately, the list of expressions finished with a statement explaining that "WatchMaker uses Lua, a scripting language used in..."

They had me at scripting language. Building a watch face would be nice. Programming one, well, that would be awesome.

Learning Lua in 24 Hours

Off to the WatchMaker Wiki I went, where I learned that WatchMaker is full powered by Lua. My entire knowledge of Lua is this: Lua is a programming language. But still, this was hugely promising. If I could run arbitrary scripts in WatchMaker, then I could effectively treat WatchMaker as an interpreter just waiting for me to writing interesting code. Before I could get too excited, I needed to get the low down on Lua.

Getting oriented with Lua was surprisingly easy. First off, I installed QLua on my Android device. This gave me access to a Lua interpreter and editor. Then I visited the online version of Learn Lua and browsed through the first few sections. I was pleased to find that QLua executed all the sample code without complaint. My iClever keyboard, LG G6 and QLua made for a hassle free learning environment.

I still don't know much about Lua, but I know that I like it. It has a Scheme feel to it, with it's small set of language constructs, reliance on a single data type for many data structures and first class functions. The embedded nature of it reminds me of TinyScheme and it's relationship with Gimp.

After about 24 hours, I had enough Lua to jump back into WatchMaker to see if I could hack something together.

Let's Get Building!

For my first WatchFace I wanted to demonstrate the ability to invoke a function that I hand coded. Turns out, that's not a tall order. At the watch properties level, there's a chance to provide a 'script.' So I wrote up a trivial version of the Factorial function and stuffed it into that field. QLua was handy in helping me verify my code outside of the WatchMaker environment.

function fact(x)
  if(x == 0)
    return 1
  else
    return x * fact(x-1)
  end
end

I then added a new layer to the watch and wrote this expression:

  {dmo} .. "!=" .. fact({dmo}) -- {dmo}

{dmo} is a magic variable that represents the one's value in the current number of minutes. In other words, if the time is 3:06, {dmo} is 6. Why did I choose {dmo}? Because it's a value that changes relatively often. I know, all this talk of functionality, and my first watch face does nothing but calculate a factorial of a useless value.

The -- {dmo} is a work around as prescribed here. I should note that the WatchMaker UI seems extremely polished. This is clearly an app with some serious development behind it.

I figured I should make my watch face at least a little usable, so I also added another layer that showed the current time.

It took a few iterations to get all this working, but when I was done I was blown away: I had programmed my first watch face. It showed the time and the result of my factorial function. To some, this may seem like a silly exercise, but to me, this shows that I can use WatchMaker as a hacking environment for the ZenWatch. The possibilities are endless!

While I was on a roll, I thought I'd broaden my horizons just a bit. Browsing the WatchMaker wiki I can across a recipe for changing color dynamically. I decided I'd incorporate this functionality into my watch face. The idea: at the start of the hour (say, 3:02) the watch would be green, as the hour progressed it would fade to purple (at say, 3:55). A quick glance at the color of the watch would show me how far through the hour I am.

Programming this was surprisingly simple. First, using QLua I coded up a function that maps a value from 0 to 1 to a color. 0 would be green, 1 would be purple:

function percent_to_color(percent)
  return string.format('%.2x%.2x%.2x',
                       percent*255,
                       (1-percent)*255,
                       percent*255)
end

After adding the above to the scripts section, I changed the background color of my watch face to this expression:

  percent_to_color({dm}/60) -- {dm}

{dm}, is as you guessed, the number of minutes in the current time. It's quite impressive that fields like background can take arbitrary expressions. To me it shows that while WatchMaker has a slick UI, it's also got serious geek cred to back it up.

Finally, here's some shots of the watch face in action:

And here's some screenshots of WatchMaker:

It isn't often that you find an app that's a game changer, but I believe that's what WatchMaker is. For anyone who wants to experiment with the world of wearable computing, or quickly develop interesting watch apps, or is just looking for a fun way to learn to program, WatchMaker belongs in your toolbox. Simply put: it's a Lua interpreter on your wrist; what more could you ask for?

No comments:

Post a Comment