\\/__,_ / \/____//\ \_\ \\/__/\/_/ \/____/ \/_/\/_/<br>/\___/ \ \____/<br>\/__/ \/___/
Powered by Hydejack v9.2.1<br>-->Stripping KiezelPay (and other network calls) from Pebble Watch Faces | Luke Rindels Jump to: Navigation
Pebble Watch Face ArchitectureModifying Pebble JSKiezelPay Watch FacesFailed AttemptsRemoving /api/v1/status callSpoofing ResponseDebugging Pebble AppsKiezelPay Status VerificationPatching Pebble BinaryPatching Pebble ChecksumsConclusion⚠️ This post is for educational purposes only. I encourage you to support the creators of great watch faces. All faces used here were paid for in full before stripping payment verification. Following the steps here may violate usage agreements and could be unlawful in your jurisdiction.<br>This week I got my first Pebble watch in the mail after pre-ordering 15 months ago!So far I’m extremely impressed with the quality and openness of the hardware and software. If you’re looking for a basic smartwatch with multi-day battery life, then I can wholeheartedly recommend the Pebble Time 2.The one thing that caused me to raise an eyebrow was seeing that many of the watch faces call out to third parties for things like weather and payment info. Watch face scripts can send information like my location to arbitrary web resources along with a unique device and account identifier.Visibility and tooling around network calls in the app itself would be nice to have, but for now I’ve resorted to stripping out the network calls myself thanks to how easy Pebble makes it to modify watch faces. The payment service most watch faces use, KiezelPay, gave me more trouble than I was expecting!Pebble Watch Face Architecture<br>There are two components to most watch faces:C code that compiles down to a binary that runs on the watch hardwareJavaScript that runs on the connected mobile deviceOnly the mobile device JS is able to make network calls.This diagram from the Pebble developer docs illustrates how the components communicate:┌─────────────┐ ┌──────────────────┐ ┌──────────────┐<br>│ Watch │ │ Phone (PKJS) │ │ Internet │<br>│ │ │ │ │ │<br>│ C code ──┼── msg ──>│ index.js ──┼── HTTP ─>│ API server │<br>│ │ │ │ │ │<br>│ │ → GPS lookup │ │ │
Let’s take a look at my current watch face Weather Land:The app store links to a Download PBW button that lets us download the watch face bundle directly. A .pbw file is just a ZIP archive, so we can extract and view its contents:unzip 4.0.pbw<br>Archive: 4.0.pbw<br>extracting: appinfo.json<br>extracting: pebble-js-app.js<br>extracting: chalk/pebble-app.bin<br>extracting: chalk/app_resources.pbpack<br>extracting: chalk/manifest.json<br>extracting: basalt/pebble-app.bin<br>extracting: basalt/app_resources.pbpack<br>extracting: basalt/manifest.json<br>extracting: aplite/pebble-app.bin<br>extracting: aplite/app_resources.pbpack<br>extracting: aplite/manifest.json
appinfo.json - Metadata about the application including name, UUID, resources, capabilities, and target platformspebble-js-app.js - Phone-side script that handles fetching network resources and communicating weather data back to the watchchalk/, basalt/, aplite/ - Each Pebble platform has its own name. See https://developer.rebble.io/guides/tools-and-resources/hardware-information/ for the list of platforms and their differencespebble-app.bin - The watch face written in C compiles down to this binary. It’s a custom executable format for Pebble watches, starting with magic header PBLAapp_resources.pbpack - Resource bundle that contains fonts and imagesmanifest.json - Timestamps, checksums, and sizes of the resource pack and pebble app binaryModifying Pebble JS<br>Let’s open up the pebble-js-app.js file for the Weather Land application and see how it works!It’s a simple script at just 200 lines and handles:Logic to choose which background to display based on current wind, time, and temperatureNetwork call to api.openweathermap.org with latitude/longitudeNetwork call to api.openweathermap.org with hardcoded locationConfiguration using reno.watch/pebble/settings.htmlI’ve turned off precise location for the Pebble app and am okay with this app fetching my approximate location for the purposes of updating weather icons.It’s a small complaint, but I’d really prefer the settings page to not be hosted externally and just live all within the app itself. I’m also not a fan of my unique account identifier being sent to the third party settings page.Pebble.addEventListener("showConfiguration", function (e) {<br>var uri =<br>"https://reno.watch/pebble/settings.html?" +<br>"use_gps=" +<br>encodeURIComponent(options.use_gps) +<br>"&location=" +<br>encodeURIComponent(options.location) +<br>"&apikey=" +<br>encodeURIComponent(options.apikey) +<br>"&units=" +<br>encodeURIComponent(options.units) +<br>"&invert_color=" +<br>encodeURIComponent(options.invert_color) +<br>"&account_token=" +<br>encodeURIComponent(Pebble.getAccountToken());<br>//console.log('showing configuration at uri: ' + uri);
Pebble.openURL(uri);<br>});
Pebble.getAccountToken() is documented at...