Pebble app development with Pebble.js

Pebble

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

PebbleKit JavaScript framework. This 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 powerfull enough for creating watchapps 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 C app that runs on the watch and interacts with the phone in order to process user actions. The Pebble.js library provides 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:

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

CloudPebble

CloudPebble environment allows you to write, build and deploy your appwatch applications both on simulator and 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 introduction let’s build Hello World application with Pebble.js. Create a new project in CloudPebble:

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:

Hello World

StackExchange profile

Getting some data from web services like weather or news is easy with 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));
}
);

The app’s view after the start:

Stackoverflow profile

Egg timer

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

  • Window is the basic building block in Pebble application. It allows to add different elements and specify a position and size for them.
  • A menu is a type of Window that displays a standard Pebble menu.
  • 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:

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

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();
}
});
Timer selection screen

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 timer, show 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);
}
Timer screen
Done message

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 pity part of the JS written applications is the requirement of constant connection to the phone. Usually Pebble.js apps need more power and respond slower than a similar native app.

Useful links

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store