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("http://www.canyouseeme.org")
  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("https://api.evrythng.com/thngs/{}/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 README.md 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 README.md 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.

Contrary to popular belief, I do other programming stuff outside of Pebble apps (as well as my other hobby – ignoring app feature requests!). One of these things is a arcade game side project that’s been on-for-a-few-weekends, off-for-a-few-months. Inspired by the sort of rapid-fire indie games my brother and his friends play (Duck Game, Samurai Gunn, Monaco, and recently Ultimate Chicken Horse), I embarked on a project to make a game similar to these that could be played by several friends around a single TV, much like local multiplayer games from my Youth (particularly Worms).

This effort saw me create a basic looping game prototype with Java2D, which began life as a top-down space-themed ship simulator, but didn’t make it very far before switching to the arcade-multiplayer genre I wanted it to become. Soon enough, drawing lots of tiles hit its max potential and so I had to spend a lot of time tearing it apart and replacing Java2D with LWJGL OpenGL for speed. The results were worth the effort, but I’m still left with an incomplete game.

Like many of my programming projects, I work on it less constantly, and more in inspired fits and bursts. So far I have intro sequences, a menu system, a tiled world system with lighting based on a novel pathfinding algorithm, up to four XBox controller support, player sprite animation and collision, and other things. But it’s still incomplete. Until I add weapons, NPCs, effects, and room generation, it’ll stay that way.

But in the meantime, I created lots of very useful sub-components that I really don’t want to have been for nothing, and will probably end up reusing in my own projects. So I decided to pull out the engine, and release it on GitHub as a standalone project that can be run independently of all the other fluff that makes up the game in progress. Importing the code into Eclipse and adding LWJGL.jar (with local libraries and binaries) will let you play around with it and build a game on top of it if you want.

Check out the GitHub repository README.md for a full list of features and how to implement it. Once I have a working prototype of the game, I’ll probably post about that as well. It’s all about the journey, right?



It’s here! The redesign I’ve been planning since many months ago (the previous colour watchapp design was a bit of a bodge), and I’ve wanted to add in a few extra features:

  • GSM signal strength
  • Wifi network name
  • Phone free space
  • Resync every 30 seconds while the app is open
  • Option to jump straight to a certain toggle when the app is opened

…and all the usual refactoring (I can’t help myself) and some protocol simplification. Here’s a rule of thumb: if your AppMessage protocol uses arithmetic and nested switch statements, ditch it!

I also improved a lot of the Android code, added fail cases, and more logging etc. to better help me diagnose problems when a user sends me a debug log. Finally, I brought a little animation magic to the UI, and relied more heavily on system UI components instead of over-complicating things by rolling my own version of everything.

Download on Google Play and Pebble appstore!

Once again, it’s been a while! The last update talked about updating apps for Chalk (Pebble Time Round), and it was around that time that I was aiming for stability on the ‘Big Three’ apps (namely Dashboard, News Headlines, and Wristponder), as well as a couple of the more popular watchfaces (namely Thin, Beam Up, Isotime, etc), so I could not be doing Pebble development all day and all night.

Happily, I eventually achieved this after a few weekend sessions, and all was good. With some interesting developments in the world of app configuration (see Clay), I added vastly improved color-selection configuration pages to those watchfaces. Color pickers beat manually entering hex strings any day of the week!

Since I’m no longer doing developer documentation/other general advocacy for Pebble (perhaps the massive Guides rewrite was my parting gift?), I have decided to try and pick it up again as a hobby, like I was doing before getting hired. I found it great fun, and very rewarding when I saw people using my apps. In general, they start life as apps I want to use my watch for, then I polish and publish them so other can find them useful.

The trouble I was running into was finding time to meet the maintenance demands of bugs/feedback from users, so now I have more time for that. Indeed, I’ve picked up a few processes/skills from my time managing my projects at Pebble that should make this process much easier. It is yet to be seen if Sheets is more efficient for a single person than JIRA, but I think I know what the answer is…


Anyway, just now I released version 3.6 of News Headlines. For some time, I’ve received the question “Can it show news from outside the UK?”. Since it started life as ‘BBC News’, that makes more sense. Yesterday I saw that the BBC has feeds for multiple regions, and so a fun exercise in adding a new feature presented itself, with a lot of potential value for users who aren’t interested in the latest scandal at Westminster.

In adding this new feature, I was reminded how complicated News Headlines is as an app, but it made the end result that much more satisfying. The process went something like this:

  • Add new enumerations for the region values.
  • Add new defaults and internal APIs for passing around the region value.
  • Add new UI items and logic to the Settings Window.
  • Add new keys for AppMessage and Persistent Storage APIs.
  • Add region-passing to the initial sync communication phase.
  • Generalise JS feed download to choose either a selected region, or a ‘category’ if the region is ‘UK’.
  • Ensure all these things played nicely for new users and also upgrading users (the latter where I’ve been stung far too many times before).
  • And as usual get massively sidetracked with refactoring and code style updates.

So now we have that. Readers around the world can make their headlines-reading experience a tad more localised if they wish. Another request I’ve been getting recently in general is to accept donations. Historically (excepting the paid version of Watch Trigger) I’ve not dabbled in donations, but since I’m not paid by Pebble anymore I will use this update to do a little experimentation. It can always be removed if nothing happens. Another experiment is making a /r/pebble subreddit post, so we’ll also see how that’s received.