This post was originally going to be a lot gloomier, but the official announcement yesterday (after a few days of utter FUD) has proven that the worst-case scenario has not come to be, and there’s reason to be optimistic about Pebble’s future.

So what better time to summarise my part of the Pebble story?

The Beginning

I backed the original Pebble in the first Kickstarter campaign, after a few weeks on the fence I was finally convinced by the promise of an open SDK. I’d had a bit of experience with C as part of my degree course, and played with Java in the second year (including prodding the Android SDK to see if I could make it do anything interesting). Why not try and make my watch do some cool things?

After the now legendary delays, I finally got my watch. It had screen tearing from the moment I turned it on, but I found that by pressing a certain part of the case I could get it to behave (Pebble replaced it within two weeks, so props to them for that). The original 1.x SDK was a bit harder to grasp than the one we have now, but even so, I eventually got my first app working:


What a moment! I could put any message I wanted on my wrist! Over the next couple of weeks I worked on a couple of watchfaces, most notable of which was Split Horizon. Back then we had MyPebbleFaces in place of an official app store, which involved the community uploading the build PBW files and then users downloading them and installing via the Android/iOS apps, which were also quite primitive at the time. Also due to the lack of app configuration, watchfaces were released in multiple listings, so Split Horizon has a Seconds Edition (animation every 15 seconds), Minutes Edition, and Plain Edition.

Once SDK 1.12 was released (two-way communication, woo!) I was able to use the first version of PebbleKit Android to do interesting things with Android APIs. The first outcome of this was Watch Trigger, the first app that allowed you to capture a photo remotely using your Pebble as the remote. This was since superseded by better efforts (PebbleCam, etc), but it was a big thing for me at the time to have this futuristic capability. I would then go on to a paid app experiment by offering a video capture upgrade (Watch Trigger +) for £0.99, and the main lesson learned was that 95% of my users loved free stuff! Here’s the second iteration (the first was just the logo!):


Hot on the heels of this was my exploration of other Android APIs. At the time, I had an Android phone (Galaxy S) that would suck power if it was connected to the wrong network. To solve this problem, I created Data Toggle to allow me to turn off WiFi when I went outside, and switch over to 3G. This would later become Dashboard as we now it today.




At the same time I also begun work on Wristponder to allow initiating and replying to SMS messages (before it was integrated into the firmware!):


The SDK Tutorials

It was that summer I started working on my SDK tutorials. Little did I know that these pieces (drafted on a notepad in Tuscany, and originally quite popular with other community members, being the only real tutorials at the time) would literally change my life.

Not shown in the image below is the pad I was writing feverishly my ideas for structured learning content that would guide through the exciting Pebble SDK opportunities:


When SDK 2.0 came out (along with PebbleKit JS, localStorage, and a better C style API) I wrote another whole multi part series out of the same motivation as the 1.x tutorial – now that I’d learned how to make this revolutionary device do my bidding, I wanted to help everyone else do the same to theirs. I still maintain that the ability to make Pebble fit into your own lifestyle (down to news stories, train delay alerts, even scheduling when your phone switches to Silent for the night) was it’s most potent feature. Especially the potential of being paired with the whole Android platform, which I hope Dashboard and the Dash API demonstrate as well as I was able.

Getting Hired

After I was almost done with the SDK 2.0 tutorials, I was contacted out of the blue on Twitter by Pebble’s lead Developer Evangelist – Thomas Sarlandie:


Originally the deal was to write some tutorials for Pebble’s Developer Blog, but that quickly turned into a full job offer. I was torn – I was in my last year of University with no job lined up, but I’d never lived out of the country before. It was such a huge opportunity I had no idea what to do. My mind was made up when one of my best uni friends said “You know your friends who are off doing amazing things travelling the world? This is your opportunity to do that too. Take it!”.

So I did.

After a few months of sorting visas, I arrived in Palo Alto and was greeted into the arranged shared accommodation by Joseph Kristoffer. The effect was incredible. I’d practically run myself into the ground finishing my fourth year of university – physically and emotionally. Being on the other side of the world in sunny California surrounded by people who wanted me there so badly was very good for me. A chance to start again, make new friends, and new first impressions.

The welcome was extremely friendly wherever you looked at Pebble, everyone wanted to know who I was and how I’d come to be in the office. I was quickly given a Macbook (which I had very little idea of how to use) and tasked with managing the original drab docs for the colourful Pebble Developer site design you see now:


After a few weeks, and a very quick crash course in git, we did it, and shipped the new site. It was bright and colourful and full of opportunity for new content. We had a company retreat and the famous 2014 Developer Retreat (with ROBOTS!!1). I got to go to Maker Faire, see the East Coast and New York on my way to YHack in Connecticut. I was having the time of my life, and knew how lucky I was at every turn.

Pebble Time

But there was little time to rest. After SDK 2.5 and the Compass API, the company threw itself into the Pebble Time project, which gradually sifted out from the Design team to the whole company. It would be more powerful, with a colour screen, a web API, and a microphone! I think the excitement started to climb when the film crew came in to film the second Kickstarter video, which if you look really carefully, you can see me in:


We launched the campaign, and there was much celebration with every million the campaign earned. It was a sign of how passionate everybody was, and how badly they wanted to make this awesome new kind of Pebble a reality, if only for at least themselves. Many of the engineers worked long hours and weekends, and famously took no voluntary holidays, their passion was that great. The same engineers who managed to fit firmware 3.x into the original hardware with mere bytes to spare. After the manufacturing started, we got some samples in the office and tried building some colour apps. I say ‘tried’, because the SDK was on the bleeding edge of what firmware functionality was built each and every day. Each new API brought more possibilities, such as the block game demo, and an early version of Isotime:


Finally, the backers started receiving watches, and the developer community responded admirably. Every day someone would be going round showing off the latest cool colour app they’d found on the app store, and I worked in my spare time to update all my apps and watchfaces to use the new colour functionality. After this we finished working on timeline, culminating in a 4AM final merge of a monstrous documentation Pull Request.

Product Owner

Sometime while writing the Smartstrap guides and the Design guides I began planning my own work and execution, with input from the rest of the team. This was completely new to me, but with a few well-maintained Google Sheets, project after project came together without issue. It was good to be more at the helm of the documentation, and being able to help all developers with useful guides, tutorials, and example apps. I also loved (and still do love!) chatting with the more active developer community members in the then Slack chat (now on Discord) and giving one on one feedback and help as much as I could.

It was during this time that we had the 2015 Developer Retreat in San Francisco, and I did fresh re-writes of the Big Four (Dashboard, News Headlines, Wristponder, and Beam Up) to make them more modular and maintainable. I’m glad I did now! I can can dive in, change some things, and only have to look at small parts of the app at any one time. I took great pleasure in perfecting my modular pattern and module interfaces, such as data_get_news_story(), or splash_window_reload_data(), allowing easy exchange of data and actions from anywhere in an app. I guess that was the result of getting better with each app I made, which is a natural part of software development, apparently.

Moving Up

Right as the office moved from Palo Alto to Redwood City (and myself getting my first apartment in RWC), we were already two months into a complete re-write of the Guides section. Reducing 78 guides crammed into ageing categories in inconsistent styles into about 60 new ones, written from the ground up show how to do everything in the same manner, from button input, to JS/Android/iOS communication (including images!), to bespoke frame-buffer drawing. I did such a thorough job that even now I frequently find myself using the snippets from those new guides in my own apps. MenuLayer? Sure, chuck that snippet in. No problem!

This last huge project was completely planned and executed by me, and I consider my last great gift to the community in an official capacity. I’m very proud of it, I won’t lie! Here’s where the magic happened, until the end:


Moving On

In March, Pebble made 25% (about 40 people) redundant, but it was made very clear it was not from a lack of good work. At the time it felt like a cost-saving measure, and now we can look back with full clarity. Since my visa was tied to my job, I had to leave the country, my apartment, my bills/utilities, furniture rental, etc, as soon as possible. I had the option of trying to transfer my visa by getting another job in the Valley, but I was quite put out by the shock of it all, so just decided to pack it all in and come home. I also had to say rushed goodbyes to about 100 people I’d come to know over the last two years. Hardest of all was the Developer Relations team, who I’d shared many adventures, days out, travel trips, etc. with. It was very hard to do, but had to be done.

I came back to the UK with everything I could fit into two airport style cases, and it was all I wanted – except my beloved walnut bass guitar, which was two inches too large (and would have cost half its value to transport properly), so I left it behind.


After Easter (which I’d spookily already booked flights and leave for), I went back to the US for a gallop around Yosemite with my Dad. We’d planned it in November 2015, planning to use my apartment to lessen the cost, but decided to go for it anyway, and boy, was it worth it!


Coming back from this trip I had no idea what I was going to do with my Pebble development. I’d sunk so much time, and accrued too many thousands of users to stop completely. But my sudden ejection back to the UK left me without any energy to do anything. Days blurred into weeks. Eventually I got it together and started looking for jobs. After about 12 attempts, I found an extremely warm and welcome home at EVRYTHNG. I can say with confidence that I wouldn’t have this job if it weren’t for Thomas taking a chance on hiring me for Pebble and giving me the credential on my CV!  I also created the Dash API to let C app developers use Android APIs, which was an interesting extension to the ecosystem.

Keeping My Hand In

I decided to maintain my apps, and only do improvements if I got the burst of energy and inspiration required to crack the dusty covers off monsters like Dashboard or News Headlines and gently coerce the insides into accepting new features. I reconnected with the developer community in my original role as a third party developer, but with some insight into how Pebble worked. But I still didn’t see the recent acquisition coming. With so many days of just rumours to go off, the community admirably began simultaneously panicking and trying to preserve everything it could in case the servers and SDK ecosystem vanished overnight. Happily, it did not, but we don’t know how long it will last.

The Future

We’re at a cross roads. It’s time for developers to keep the flame alive, as I know they can and want to do. I foresee a time when the servers are gone (no app login, timeline, lockers, dictation, etc), but we can still keep going with side-loaded apps (remember MyPebbleFaces? Ahead of its time, perhaps) until the watches die!

And that’s what I intend to do. I’ll still maintain my apps (since the most popular ones I happen to use myself every day) as long as it is possible to do so with the SDK ecosystem. I used to have an Android app to distribute my Pebble app/face’s PBW files, but it was a nightmare to keep in sync with the app store. Now the latter may one day disappear (or it may not!), I will dust it off and use it to preserve my offerings for all who are interested.

In addition to this maintenance, I will also be completing my open-source collection – including the Big Four! Well, Beam Up is already open source, so that leaves Dashboard, News Headlines, and Wristponder. Understand that this isn’t because I’m abandoning them – this recent shift has put emphasis on the community carrying the torch, and this is the best way to keep contributing to the whole and helping others learn how things are done. And maybe now it’ll force me to clean the code up! So look out for those in the next few weeks, when I get round to them in my free time. And I’ll save time by not needing to upgrade them to Emery’s display… bitter sweet.

For now, you can see all my open source apps on my GitHub account.


I hope it’s passively become clear in reading this piece how much of a personal impact Pebble has had on my life. The experience of living and working in Palo Alto patched me up after my gruelling final year of uni. I got to see and experience things and places I never would have otherwise. I got to meet and make friends with so many Team Pebble members, and so many Pebble Developer community member too, who I very much hope to keep collaborating with into 2017 and hopefully beyond. So many people, places, occasions captured in so many photos –  I would never be able to post them all. But I am lucky to be able to look back fondly on all the good times.


In the words of what I imagine Eric said at the company’s inception: “Let’s see how far we can take this thing!”




Here’s a little something to take everybody’s mind of things.


This is a neat idea I had a while ago but only just got around to doing –

“What would a map of all the interconnections and services that my Pebble apps rely upon look like?”

Well, thanks to the neat tool that is Google Drawings, here it is. Scary dependencies!


Of course, this isn’t the full picture. The Server Pi and Monitor Pi provide me with useful services I use in my day-to-day life, such as train delay timeline pins, weather alerts, and updates on the health of the services apps rely upon. Those details aren’t shown here for brevity, but would increase the complexity of the drawing about 50%.

I’m a big fan of Blinkt light hats for Raspberry Pi. I have one showing me server status, rail delays, and weather conditions.


Server down!

I have another at work showing the status of the last link check on our site.


And now I have one as a dynamic backlight for my new PC build.


And the best part? This last one has an API! It has five modes, powered by a Node.js Express server and the node-blinkt NPM package:

  • /set { "to": [r, g, b] } – Set a color instantly.
  • /fade { "to": [r, g, b] } – Fade from the current colour to this one.
  • ‘CPU’ – Fade to a colour on a HSV scale from green to red depending on current CPU load.
  • ‘Screen’ – Take an average of the four screen corners, and set to that colour ten times a second.
  • ‘Demo’ – Fade to a random colour from the rainbow every 15 seconds.
  • ‘Test’ – Ping the Pi and set the ‘Test’ button to green if it responds ‘OK’ and HTTP 200.

The last three are driven by a Java control panel that permanently lives on the new PC.


Thanks to the motherboard supplying power after the PC turns off, I can use ‘Demo’ as a nightlight! Not that I need one…

Update: Added changed IP facility details.

Update: Added status watchapp details.

Two of my Pebble apps push pins to the timeline to enhance their experience beyond the apps themselves:

  • News Headlines – Posts the top headline (if it’s new) every four hours. Used to push notifications and serve decoded PNG images, but that went away. Maybe someday they will return. But not for now.
  • Tube Status – Checks the TFL feed every five minutes, and pushes a pin if there is a change in the delay status. This can be a new delay, a delay that’s ended, and ‘all clear’ (no delays anymore).

Both servers also respond to GET /status to show app users if they’re up, and this has proved useful when they occasionally went down. Thanks for a ‘do node index.js forever’ loop script, this is very rarely now an issue.

Up until now, these pins were served from a $5 Digital Ocean instance which essentially spends 99.9% of its time doing absolutely nothing! After coming back to the UK and making progress towards cancelling subscriptions and emptying my US bank account, I had a better idea – use my dusty Raspberry Pi instead!

As part of my new job at EVRYTHNG, a natural avenue of exploration for getting to grips with the IoT is using a Raspberry Pi, which can run Node.js, as it turns out. Perfect! The pin servers for the two apps above use Node.js with Express.

So after a bit of code/dependency cleanup, I set up both servers on the Pi with screen and put plenty of stickers around warning against turning it off or rebooting the router.

So far, so good! What could go wrong?


The new ‘Pin Pusher’ Raspberry Pi in its native habitat – under the family computer desk.

Followup: Getting a Changed Router IP while Out the House

In the eventuality that I have to update the IP of the family router for apps to use in their status check (otherwise they think the servers have gone down, bad for users!), I used to have a Python script email me its own IP address. Sadly, Google doesn’t like this unauthenticated use of my GMail account, so I devised an alternative.

I set up my Pi as an EVRYTHNG Thng, gave it an ‘ip’ property, and wrote the following Python script to update this property in the EVRYTHNG cloud when it boots up. This way, all I have to do is ask whoever’s in to reboot the Pi, and then wait for the updated IP address! I may also make it run periodically to cover the ‘router randomly restarted’ scenario.


import requests
import socket
import fcntl
import struct
import json

user_api_key = "<key>" # Probably shouldn't publish this!
thng_id = "<id>"

def get_ip_address(ifname):
  r = requests.get("")
  spool = r.text
  start_str = "name=\"IP\" value=\""
  start_index = spool.index(start_str) + len(start_str)
  spool = spool[start_index:]
  end_index = spool.index("/>") - 1
  return spool[:end_index]

def main():
  ip = get_ip_address("eth0")
  print("IP: {}".format(ip))

  headers = {
    "Authorization": user_api_key,
    "Content-Type": "application/json",
    "Accept": "application/json"
  payload = [{
    "value": ip
  r = requests.put("{}/properties/ip".format(thng_id), headers=headers, data=json.dumps(payload))
  res = r.text


Followup: Checking Status Conveniently

Each of the two apps mentioned above have a built-in server monitoring feature in their settings screens, but that’s a lot of scrolling. To put my mind at ease I have also created a simple monitoring app that uses the same backend mechanism:


A few days ago, an interesting idea came up in the PebbleDev Slack channel: could a library make it easier for Pebble developers to integrate their apps with Android APIs, but save the pain of each and every one of them needing to publish an app with PebbleKit Android? This would be similar to how Dashboard operates, but by sharing the API access to other apps that are installed.

Turns out, it can! In one of my signature coding bursts I set to work, and prototyped a system that did just this. The result is the Dash API. With it, you can finally (and easily) provide one of the most common watchface widget requests – things like the phone’s battery level, or connectivity status.

How does it work?

The Dash API (named after Dashboard) Pebble package uses AppMessage to send requests to read data (such as WiFi network name, or phone battery level), or write to an API (such as turning off WiFi). Using a unique key to recognise Dash API messages, the Android app can respond to these by reading the data or manipulating the Android API and returning a response code. All the developer needs to do is instruct their users to install my Dash API Android app, and then their app (and any others that use the Dash API) can take advantage of the APIs presented through the library. This approach makes the Dash API an install once, use in many apps service.

The upshot of all this is that a C developer making a watchface that wants to show the phone battery level (such as the demo app Dual Gauge) need only use the Pebble package and not write a single line of Java, let alone go to the trouble of publishing an Android app on Google Play.

But how can one companion app target them all, without knowing they exist?

Luckily, you can extract the UUID of an app that sends an AppMessage packet to the phone from the Intent object broadcast from the Pebble Android app. Most (hopefully app) companion apps that manually register a BroadcastReceiver do a ‘good citizen’ UUID check to make sure they only respond to messages from their corresponding watchapp. This data can be used to simply redirect an incoming message’s result right back at it, without the need to create a PebbleKit Android app with baked in UUID for each individual app.

So how can I use it?

Simple. As explained in the GitHub file, a C developer should first install the package:

$ pebble package install pebble-dash-api

Next, include the single library file and call the initialiser when your app is starting, supplying the app’s name (for presentation in the Android app) and an error callback for receiving any errors that may occur:

#include <pebble-dash-api/pebble-dash-api.h>;
#include <pebble-events/pebble-events.h>

#define APP_NAME "My App"

static void error_callback(ErrorCode code) {
  // Receive error codes here

static void init() {
  dash_api_init(APP_NAME, error_callback);

  /* Other init code */

Next, check the Android app is available and up to date:


The result will be passed to your error_callback. Once you get ErrorCodeSuccess, it is safe to start making queries, such as getting the battery level, etc. Code examples are included in the GitHub file.

What else do I need to know?

As of 1.1 (released today), apps that read data and API states can do so invisibly. However, apps that wish to write to an API (such as turning off WiFi) will cause a notification to appear that will prompt the user to grant it access within the Dash API app. Once this is done, operation will continue without further intervention, unless permission is revoked. This should hopefully prevent any rogue apps messing with the phone, and give users visibility into which Pebble apps they have used are using the Dash API.


GitHub Repo

Dash API Android app (direct your users here!)

NPM Package

Example App (Dual Gauge)

What’s next?

In the future, I’d like to expand the capabilities offered by the Dash API to other popular widget requests, things such as unread SMS count and next Calendar appointment. Perhaps for another day – coordinating GitHub repos, NPM packages, Android apps, and Pebble apps is quite tiring!

That’s right, the latest and greatest update to Dashboard is now live (pending Google Play deployment delay). The new features are (in descending order of number of requests received):

  • A choice of Find Phone sound from system notification sounds. While these are guaranteed to be available, free-form choice of file proved too tricky to handle (see Android file manage content:// URI problems discussed elsewhere).
  • An option to post an Android notification (and by extension, to the watch) when the phone has fully charged (see details below). This approach is better than the original one planned which involved custom UI in the watchapp, but would rely on an assumption about how long PebbleKit Android would take to launch the watchapp before messaging it.
  • Holding down the button now uses repeat button clicks to reduce wear on the Pebble buttons while scrolling through toggles.
  • Since I’m making bigger use of Notifications, installed a proper white notification icon to improve upon the old ‘white circle’.
  • More misc UI improvements in both app components, including a donation link for those inclined, after some minor success in News Headlines.

So how does the new ‘full charge notification’ feature work? I’m glad you asked!

The Short Answer

Once your phone has reached 100% charge (when it was previously 99% or less), an Android notification is posted, which is displayed on Pebble (for free!) unless for some reason Dashboard was disabled in the Pebble app.

The Long Answer

Oh boy, this was a tricky one. While the ACTION_BATTERY_CHANGED Intent is available for apps to know when the battery level changes, it’s a special case that cannot be simply registered in AndroidManifest.xml for spin-up whenever required. It has to be programmatically registered. For an app designed to run with extremely minimal interaction with the Android app component, this is tricky.

So what have I done? When the user toggles the feature on in the Android app, the BroadcastReceiver for the above Intent is registered. Sounds simple, right? Well that works for anywhere between ten minutes and an hour or so. I was charging my phone from 99% in testing, and seeing the notification after a few minutes as expected, but a frustrating lack of notification after leaving the phone idle for couple of hours on longer charges.

For reasons unknown to me, the system kills my programmatically registered BroadcastReceiver at seemingly random intervals. Remember, this wouldn’t happen with a nice and convenient receiver registered in AndroidManifest.xml.

Undeterred by this (because this is a nice feature idea), I found another solution. I made the receiver object a static class member, and used the Android AlarmManager to check it was not null at infrequent intervals (currently half an hour). This seemed to work well, once I realised by trial and error that Android Studio appears to kill BroadcastReceivers and AlarmManager alarms, but not deliver the ACTION_PACKAGE_CHANGED which I use to restore the alarms after a theoretical future app update is installed.

In addition, new users would not have their ‘keep alive’ alarms registered upon first install, since ACTION_PACKAGE_ADDED is not delivered to the app that has just installed (why!?). Fancy another complication? Here you go: AlarmManager alarms are all killed when the device is rebooted, so I make additional use of ACTION_BOOT_COMPLETED to restore them.


So there we go! I’ve always been a vocal proponent of Android’s Intent system for IPC, but after this set of complications (which has still yielded an apparently solid solution), I’m not so sure. Ah, who am I kidding? Still a big fan!

Dashboard can be installed from the Pebble appstore and the Google Play Store.

So Pebble recently added proper library support to their SDK. Fantastic! Now I have a streamlined outlet for all my obsessive and productive refactoring. A lot of my apps and watchfaces contain modular elements that get reused. I also have a strange draw to making libraries, examples of which you can find in this handy GitHub README.

After the feature went live, I spent some time reviewing work done by Cherie, and published two libraries on NPM (more will probably follow, if I find the time/energy):

  • pebble-pge – Everybody’s favourite Pebble game engine they’ve probably never heard of.
  • universal-fb – Universal access to set/get/swap colours in a Layer’s LayerUpdateProc without having to worry about the buffer format/how to manipulate bits in bytes (I already did that for you, twice)

This concludes today’s library announcements.

In other news, I finally caved an made the icon grid/menu compromise in Dashboard that the more vocal users were complaining about. I have to admit, cramming both screens into one Window with an animation between them does work very well, and is likely to be the status quo for some time to come.

Speaking of which, watching the latest Developer Meetup video made me sad to no longer be a part of improving the Pebble Development experience, but excited to remain a community member and spend even more time putting off adding new features to my apps that are enabled by the new SDK APIs. I’m looking at you, App Glances.