Developing

Pebble WatchApp

with PebbleJS

What I've learned.

YuLun Shih

  • Python
  • JavaScript & Node.js
  • Sanji Framework

Sanji Framework

Coming soon...

Pebble Watch

Daring Fireball - "The watch itself is a very cool idea; I'm in as a backer"

Forbes - "Proven track record...Incredibly useful product"

Engadget - "Allerta intros Pebble smartwatch, inPulse's attractive younger sibling"

Wired Gadget Lab - "Smartwatches haven't really caught on with mainstream buyers - but that might change with Allerta's new wrist-worn creation"

The Verge - "...a smartwatch that might strike one of the best balances between functionality and power drain to date"

William Gibson - "Kickstart [a] nice e-paper watch! Your Backer, e pluribus unum!"

r/Android - p1zz4guy "I started throwing money at my computer screen while reading this"

PandoDaily - "Pebble is a smartwatch done right"

CUSTOMIZE BY CODING

Pebble can receive simple alerts and notifications from if this then that (ifttt.com) or our web-facing RESTful endpoint.

 

More adventurous developers can use the Pebble SDK, with its Arduino-like abstractions and simple C structure, to

 

Gain Full Control of the Watch

 

Multiple apps can run on Pebble, along side watchfaces and regular notifications.

After a while...

IOS

Android
Pebble.js

Pebble C

The Pebble C SDK, used for creating native watchapps and watchfaces.

PebbleKit iOS

Objective-C library for creating companion apps that interface iOS and Pebble.

PebbleKit Android

Java library for creating companion apps that interface Android and Pebble.

PebbleKit JS

JavaScript component of a Pebble app that leverages features of the connected phone to enhance watchapp capabilities.

Pebble.js

Create watchapps using only JavaScript code, which controls a provided native watchapp over Bluetooth.

Pebble.js

announced during JSConf 2014!

Pebble.js applications run on your phone. They have access to all the resources of your phone (internet connectivity, GPS, almost unlimited memory, etc). Because they are written in JavaScript they are also perfect to make HTTP requests and connect your Pebble to the internet.

JavaScript Rocks!

Released under MIT License

Uber Now

Talk is cheap. Show me the code.

―Linus Torvalds

/* Require libs */
var UI = require('ui');
var Vector2 = require('vector2');
var ajax = require('ajax');
var Vibe = require('ui/vibe');
var Accel = require('ui/accel');
Accel.init();

/* Variables */
var APP_VERSION = "v2.2";
var isUpdating = false;
var lastUpdate = (new Date).getTime();
var locationOptions = {"timeout": 15000, "maximumAge": 30000,
                       "enableHighAccuracy": true};


/* UI Elements */
var main_window = new UI.Window();
var info_text = new UI.Text({
  position: new Vector2(0, 50),
  size: new Vector2(144, 30),
  font: 'gothic-24-bold',
  text: 'Uber Now',
  textAlign: 'center'
});
var anykey_text = new UI.Text({
  position: new Vector2(0, 114),
  size: new Vector2(144, 30),
  font: 'gothic-14-bold',
  text: 'Press any key to update',
  textAlign: 'center'
});


/* Image Mapping List */
var image_list = {
  uberx: "images/mono-uberx.png",
  uberxl: "images/mono-uberxl2.png",
  uberblack: "images/mono-black.png",
  uberexec: "images/mono-black.png",
  ubersuv: "images/mono-suv.png",
  ubertaxi: "images/mono-taxi.png",
  ubert: "images/mono-nytaxi4.png"
};


function locationSuccess(pos) {
  console.log(JSON.stringify(pos.coords));
  fetchUber(pos.coords);
}

function locationError(err) {
  console.warn('location error (' + err.code + '): ' + err.message);
  info_text.text('Can\'t get location.');
  info_text.font('gothic-18-bold');
  isUpdating = false;
}

function firstUpperCase(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

function showUber(data) {
  var times = data.times;
  if (times.length === 0 && data.is_available) {
    info_text.text('No cars available');
    info_text.font('gothic-24-bold');
    return;
  } else if (data.is_available === false) {
    info_text.text('No cars available');
    info_text.font('gothic-24-bold');
    return;
  }

  var items = [];
  times.forEach(function(product) {
    product.surge_multiplier = product.surge_multiplier || 1;
    product.display_name = firstUpperCase(product.display_name);
    var title = product.display_name;
    if (product.surge_multiplier !== 1) {
      title += ' *' + Number(product.surge_multiplier).toFixed(2);
    }
    var item = {
      title: title,
      subtitle: 'pick up time: ' +
                Math.ceil(product.estimate / 60) + ' mins',
      product: {
        display_name: product.display_name,
        capacity: product.capacity,
        image: product.image,
        description: firstUpperCase(product.description)
      }
    };
    items.push(item);
  });

  var menu = new UI.Menu({
    sections: [{
      items: items
    }]
  });

  menu.on('select', function(e) {
    var product = e.item.product;
    if (product.capacity && product.image && product.description) {
      var image = image_list[e.item.title.toLowerCase()] ||
                             'images/mono-black.png';
      var card = new UI.Card({
        banner: image,
        title: product.display_name,
        body: "Capacity: " + product.capacity + '\n' + product.description,
        scrollable: true
      });
      card.show();
    }
  });

  menu.show();
}

function fetchUber(coords) {
  var params = 'latitude=' + coords.latitude +
               '&longitude=' + coords.longitude +
               '&pebble=' + APP_VERSION;
  ajax({ url: 'http://pebble-uber.yulun.me/?' + params, type: 'json' },
    function(data) {
      info_text.text('Uber Now');
      info_text.font('gothic-24-bold');
      Vibe.vibrate('double');
      showUber(data);
      lastUpdate = (new Date).getTime();
      isUpdating = false;
    },
    function(error) {
      if (error.message) {
        info_text.text(error.message);
      } else {
        info_text.text('Connection Error');
      }
      info_text.font('gothic-18-bold');
      isUpdating = false;
    }
  );
}

function _update() {
  isUpdating = true;
  info_text.text('Searching...');
  info_text.font('gothic-24-bold');
  window.navigator.geolocation.getCurrentPosition(locationSuccess,
                                                  locationError,
                                                  locationOptions);
}

function update(force) {
  var diffTime = Math.abs(lastUpdate - (new Date).getTime());
  if (diffTime <= 1000  || isUpdating) return;
  _update();
}

main_window.on('click', 'up', update);
main_window.on('click', 'down', update);
main_window.on('click', 'select', update);
Accel.on('tap', update);

// Init
main_window.add(anykey_text);
main_window.add(info_text);
main_window.show();
_update();

That's see what we got

EASY! (Uber Now LOC: < 170 lines)

 

XHR and WebSocket are supported on iOS and Android

 

window.navigator.geolocation.getCurrentPosition

CLOUDPEBBLE

Write apps without dealing with Linux, virtual machines, compilers, or Python.

Deploy & Debug

Demo

Let's talk about

Promotion

Hacker News

Social News

Computer Science

Entrepreneurship

Product Hunt

share and discover new products

Others

Don't be shy show us your awesome projects

Wearable 
JavaScript
Cloud

One
      More
            Thing

Analytics for Developers

with keen.io

Analytics SDKs

  • Javascript
  • iOS
  • Android
  • Java
  • Node
  • PHP
  • Python
  • Ruby
  • cURL
  • .NET
  • Scala
  • Parse
client.addEvent("invaild request", {
    ip: ip,
    url: req.url
});

client.addEvent("no service request", {
    ip: ip,
    url: req.url,
    result: {
        times: times,
        is_available: is_available
    }
});

client.addEvent("success request", {
    ip: ip,
    url: req.url,
    result: {
        times: times,
        is_available: is_available
    }
});

Very Simple & Easy

Workbench

var client = new Keen({
  projectId: "your_project_id",
  readKey: "your_read_key"
});
Keen.ready(function(){
  var query = new Keen.Query("count", {
    eventCollection: "success request"
  });
  client.draw(query, document.getElementById("my_chart"), {
    // Custom configuration here
  });
});

Users from World Wide

GeoJSON? That's another story...

Made with Slides.com