It's all in the wrist: How to write apps for the Pebble smartwatch

Code and example video - the (bouncing on-screen) ball's in your court

The Power of One Infographic

It all clicks

Let’s add some user interaction. Pebble OS now uses a system akin to its event handling mechanism, the better to help the coder give the user more ways to control the three-button watch. This lets you directly accommodate single clicks short and long, double-clicks, and press-and-hold events, rather than simply waiting for a push on a specific button and then trying to deal with the user’s intentions.

The Pebble SDK, then, defines a ClickConfigProvider entity which is essentially an array of function calls for specific buttons and the various ways each of them can be used. This list of calls is attached to the host window.

Pebble smartwatch

The Pebble’s three buttons for user interaction

First, we need to add the line

    window_set_click_config_provider(&window, (ClickConfigProvider)config_provider);

to the handle_init() initialisation function, and we need to run it after the app’s Window - reached using the pointer variable window - has been pushed onto the OS’s Window stack, or it will be ignored. The above line tells the window where to get its array of button configurations from, which it does by calling a second function, the config_provider passed in the first call. Here’s what it looks like in our app:

void config_provider(ClickConfig **config, Window *window)
    config[BUTTON_ID_UP]->click.handler = (ClickHandler)up_single_click_handler;
    config[BUTTON_ID_DOWN]->click.handler = (ClickHandler)down_single_click_handler;

We punch into the array of configurations handlers for the button-related events we’re interested in. Here, that’s a couple of single-click handlers, added to the click.handler, fields, but we could have added function calls for each button’s multi_click.handler, its long_click.handler and/or its long_click.release_handler fields. Other fields specify how many clicks in a group we’re interested in, or whether we’re only interested in the final click in a batch - it doesn’t matter how many times the user presses the button in rapid sequence, we just deal with the last one. The mechanism can handle hold-to-repeat actions too.

With your handlers registered this way, all you have to do now is write the handlers themselves. This app uses the top and bottom buttons to trigger a sudden change in the bouncing ball’s direction:

void up_single_click_handler(ClickRecognizerRef recognizer, Window *window)
    delta_x = delta_x * -1;


void down_single_click_handler(ClickRecognizerRef recognizer, Window *window)
    delta_y = delta_y * -1;

These handlers and, indeed, the config_provider function require declarations at the top of the file, or in a separate header file if you’re using one.

Updating the ball’s movement every second doesn’t make for a very dynamic display, of course. As I say, Pebble OS’ .tick_info handler doesn’t generate more than one event a second, so we’ll have to use its timer_handler instead. To do so, edit the pbl_main function, to remove the .tick_info section from the list of PebbleAppHandlers and replace it with .timer_handler = &handle_timer. The function should now look like this:

void pbl_main(void *params)
    AppContextRef ctxt = (AppContextRef) params;
    PebbleAppHandlers handlers =
        .init_handler = &handle_init,
        .deinit_handler = &handle_deinit,
        .timer_handler = &handle_timer
    app_event_loop(ctxt, &handlers);

You’ll notice that I’ve also added a second new handler, .deinit_handler, which is called when the app quits, and is here used to politely cancel any timers in the event queue that have yet to fire:

void handle_deinit(AppContextRef ctxt)
    app_timer_cancel_event(ctxt, timerHandle);

The value timerHandle is a global variable declared at the start of the program alongside Window window. It provides a reference to the AppTimerHandle timer in memory. We’ll set this up in the handle_init() with an extra line at the end of that function:

    timerHandle = app_timer_send_event(ctxt, 500, 1);

It takes the usual AppContextRef pointer to the app itself, a time in milliseconds before which the timer fires - half a second here - and a unique integer, called a “cookie” by the SDK, to identify the specific timer to the handler when you’re running more than one at once. The timer’s handle and its cookie value are passed to the timer handler function when it’s triggered, so you can check which timer has triggered the code.

Delete the handle_tick() function if you like, but copy it first to form the basis for your handle_timer() function:

void handle_timer(AppContextRef ctxt, AppTimerHandle handle, uint32_t cookie)
    pos_x = pos_x + delta_x;
    pos_y = pos_y + delta_y;
    if (pos_x > 140)
        pos_x = 132;
        delta_x = -8;
    if (pos_x < 4)
        pos_x = 12;
        delta_x = 8;
    if (pos_y > 162)
        pos_y = 154;
        delta_y = -8;
    if (pos_y < 4)
        pos_y = 12;
        delta_y = 8;
    timerHandle = app_timer_send_event(ctxt, 100, 1);
    Layer *root = window_get_root_layer(&window);

One extra line goes in, to call the app_timer_send_event() function as per the line in handle_init(). As yet, Pebble OS timers don’t fire continuously, so we add a new one to the event queue each time the timer fires. I’ve set this time to 100ms.

Compile the app, transfer it to your watch, select it from the Pebble’s menu and you should see a ball moving at a moderate pace around the screen. You can change its direction with a press of the top or bottom buttons. Not very impressive, of course, but the code I've outlined here can form the basis for much more interesting and more useful apps.

Top three mobile application threats

Next page: Resources boom

More from The Register

next story
NEW Raspberry Pi B+, NOW with - count them - FOUR USB ports
Composite vid socket binned as GPIO sprouts new pins
Child diagnosed as allergic to iPad
Apple's fondleslab is the tablet dermatitis sufferers won't want to take
Microsoft takes on Chromebook with low-cost Windows laptops
Redmond's chief salesman: We're taking 'hard' decisions
For Lenovo US, 8-inch Windows tablets are DEAD – long live 8-inch Windows tablets
Reports it's killing off smaller slabs are greatly exaggerated
Seventh-gen SPARC silicon will accelerate Oracle databases
Uncle Larry's mutually-optimised stack to become clearer in August
EU dons gloves, pokes Google's deals with Android mobe makers
El Reg cops a squint at investigatory letters
prev story


Top three mobile application threats
Prevent sensitive data leakage over insecure channels or stolen mobile devices.
The Essential Guide to IT Transformation
ServiceNow discusses three IT transformations that can help CIO's automate IT services to transform IT and the enterprise.
Mobile application security vulnerability report
The alarming realities regarding the sheer number of applications vulnerable to attack, and the most common and easily addressable vulnerability errors.
How modern custom applications can spur business growth
Learn how to create, deploy and manage custom applications without consuming or expanding the need for scarce, expensive IT resources.
Consolidation: the foundation for IT and business transformation
In this whitepaper learn how effective consolidation of IT and business resources can enable multiple, meaningful business benefits.