6 min read

Pebble is a smartwatch that pairs with both Android and iPhone devices via Bluetooth. It has an e-paper display with LED backlight, accelerometer and compass sensors. On top of that battery lasts up to a week between charges. From the beginning Pebble team embraced the Developer community which resulted in powerful SDK. Although a primary language for apps development is C, there is a room for JavaScript developers as well.

PebbleKit JS

The PebbleKit JavaScript framework expands the ability of Pebble app to run JavaScript logic on the phone. It allows fast access to data location from the phone and has API for getting data from the web. Unfortunately app development still requires programming in C. I could recommend some great articles on how to get started.

Pebble.js

Pebble.js, in contrast to PebbleKit JS, allows developers to create watchapp using only JavaScript code. It is simple yet powerful enough for creating watch apps that fetch and display data from various web services or remotely control other smartdevices. The downside of that approach is connected to the way how Pebble.js works. It is built on top of the standard Pebble SDK and PebbleKit JS. It consists of a C app that runs on the watch and interacts with the phone in order to process user actions. The Pebble.js library provides an API to build user interface and then remotely controls the C app to display it. As a consequence of the described approach watchapp couldn’t function without a connection to the phone. On a side note, I would mention that library is open source and still in beta, so breaking API changes are possible.

First steps

There are 2 options getting started with Pebble.js:

  1. Install Pebble SDK on your local machine. This option allows you to customize Pebble.js.
  2. Create a CloudPebble account and work with your appwatch projects online. It is the easiest way to begin Pebble development.

CloudPebble

The CloudPebble environment allows you to write, build and deploy your appwatch applications both on a simulator and a physical device. Everything is stored in the cloud so no headache with compilers, virtual machines or python dependencies (in my case installation of boost-python end up with errors on MacOS).

Hello world

As an introduction let’s build the Hello World application with Pebble.js. Create a new project in CloudPebble:

Pebble Watch Development with Pebble.js

Then write the following code in the app.js file:

// Import the UI elements
var UI = require('ui');

// Create a simple Card
var card = new UI.Card({
  title: 'Hello World',
  body: 'This is your first Pebble app!'
});

// Display to the user
card.show();

Start the code on Pebble watch or simulator and you will get the same screen as below:

Pebble Watch Development with Pebble.js

StackExchange profile

Getting some data from web services like weather or news is easy with an Ajax library call. For example let’s construct an app view of your StackExchange profile:

var UI = require('ui');
var ajax = require('ajax');

// Create a Card with title and subtitle
var card = new UI.Card({
  title:'Profile',
  subtitle:'Fetching...'
});

// Display the Card
card.show();

// Construct URL
// https://api.stackexchange.com/docs/me#order=desc&sort=reputation&filter=default&site=stackoverflow&run=true
var API_TOKEN = 'put api token here';
var API_KEY = 'secret key';
var URL = 'https://api.stackexchange.com/2.2/me?key=' + API_KEY + '&order=desc&sort=reputation&access_token=' + API_TOKEN + '&filter=default';

// Make the request
ajax(
  {
    url: URL,
    type: 'json'
  },
  function(data) {
    // Success!
    console.log('Successfully fetched StackOverflow profile');
   
    var profile = data.items[0];
    
    var badges = 'Badges: ' + profile.badge_counts.gold + ' ' + profile.badge_counts.silver + ' ' + profile.badge_counts.bronze;
    // Show to user
    card.subtitle('Rep: ' + profile.reputation);
    card.body(badges + 'nDaily change:' + profile.reputation_change_day + 'nWeekly change:' + profile.reputation_change_week + 'nMonthly change:' + profile.reputation_change_month);
  },
  function(error) {
    // Failure!
    console.log('Failed fetching Stackoverflow data: ' + JSON.stringify(error));
  }
);

Egg timer

Lastly I would like to create a small real life watchapp. I will demonstrate how to compose a Timer app for boiling eggs. Let’s start with the building blocks that we need:

  1. Window is the basic building block in Pebble application. It allows you to add different elements and specify a position and size for them.
  2. A menu is a type of Window that displays a standard Pebble menu.
  3. Vibe allows you to trigger vibration on the wrist. It will signal that eggs are boiled.

Egg size screen

Users are able to select eggs size from options:

  1. Medium
  2. Large
  3. Extra-large
var UI = require('ui');

var menu = new UI.Menu({
    sections: [{
      title: 'Egg size',
      items: [{
        title: 'Medium',
      }, {
        title: 'Large'
      }, {
        title: 'Extra-large'
      }]
    }]
  });

menu.show();

Pebble Watch Development with Pebble.js

Timer selection screen

On the next step user selects timer duration. It depends whether he wants soft-boiled or hard-boiled eggs. The second level menu for medium size looks like:

var mdMenu = new UI.Menu({
    sections: [{
      title: 'Egg timer',
      items: [{
        title: 'Runny',
        subtitle: '2m'
      }, {
        title: 'Soft',
        subtitle: '3m'
      }, {
        title: 'Firm',
        subtitle: '4m'
      }, {
        title: 'Hard',
        subtitle: '5m'
      }]
    }]
  });

  // open second level menu from the main
  menu.on('select', function(e) {
    if (e.itemIndex === 0){
      mdMenu.show();
    } else if (e.itemIndex === 1){
      lgMenu.show();
    } else {
      xlMenu.show();
    }
});

Pebble Watch Development with Pebble.js

Timer screen

When timer duration is selected we start a countdown.

mdMenu.on('select', onTimerSelect);
lgMenu.on('select', onTimerSelect);
xlMenu.on('select', onTimerSelect);

// timeouts mapping from header to seconds
var timeouts = {
  '2m': 120,
  '3m': 180,
  '4m': 240,
  '5m': 300,
  '6m': 360,
  '7m': 420
};

function onTimerSelect(e){
  var timeout = timeouts[e.item.subtitle];
  timer(timeout);
}

The final bit of the watchapp is to display a timer, show a message and notify the user with vibration on the wrist when time is elapsed.

var readyMessage = new UI.Card({
  title: 'Done',
  body: 'Your eggs are ready!'
});

function timer(timerInSec){
  var intervalId = setInterval(function(){
    timerInSec--;

    // notify with double vibration
    if (timerInSec == 1){
      Vibe.vibrate('double');
    }
    if (timerInSec > 0){
      timerText.text(getTimeString(timerInSec));
    } else {
      readyMessage.show();
      timerWindow.hide();

      clearInterval(intervalId);

      // notify with long vibration
      Vibe.vibrate('long');
    }
  }, 1000);
  
  var timerWindow = new UI.Window();
  var timerText = new UI.Text({
    position: new Vector2(0, 50),
    size: new Vector2(144, 30),
    font: 'bitham-42-light',
    text: getTimeString(timerInSec),
    textAlign: 'center'
  });

  timerWindow.add(timerText);
  timerWindow.show();
  timerWindow.on('hide', function(){
    clearInterval(intervalId);
  });
}

// format remaining time into 00:00 string
function getTimeString(timeInSec){
  var minutes = parseInt(timeInSec / 60);
  var seconds = timeInSec % 60;
  return minutes + ':' + (seconds < 10 ? ('0' + seconds) : seconds);
}

Pebble Watch Development with Pebble.js

Conclusion

You can do much more with Pebble.js:

  • Get accelerometer values
  • Display complex UI mixing geometric elements, text and images
  • Animate elements on the screen
  • Use the GPS and LocalStorage on the phone
  • Timeline API is coming

Pebble.js is best suited for quick prototyping and applications that require access to the Internet. The unfortunate part of the JavaScript written applications is the requirement of a constant connection to the phone. Usually Pebble.js apps need more power and respond slower than a similar native app.

Useful links

About the author

Eugene Safronov is a software engineer with a proven record of delivering high quality software. He has an extensive experience building successful teams and adjusting development processes to the project’s needs. His primary focuses are Web (.NET, node.js stacks) and cross-platform mobile development (native and hybrid). He can be found on Twitter @sejoker.

LEAVE A REPLY

Please enter your comment!
Please enter your name here