Creating a simple Smartwatch app

Creating a simple Smartwatch app

So seeing as Fitbit bought Pebble, and development is going to end on the Pebble platform, everyone is selling off their stock of Pebbles cheap. And I love a bargain. So I bought a Pebble Time (partly in the hope I finally find a killer app for the things and can retire to my own secret volcanic island base with the proceeds). Of course, I had to have a play with the SDK.

I bought the colour screen model and, thanks to the eInk screen, it really does last 7 days on one charge (as long as your watchface updates every minute, not every second) from Amazon for £50. I reckon you might be able to get it cheaper if you shop around.

For those who don’t know what a Pebble is, well its the first of the modern smartwatches. It is not tied to a particular platform so works on Android and IOS. It tells the time. It also displays notifications for messages, emails etc… Sadly is does not feature a microphone, so I can’t pretend I’m a spy.

And it lets you change the watchface. Whats more you can create your own using the cloud based development tools. The watchface is actually a self contained app, hence the title of this post. So here’s my views after a few hours playing with the development tools and using the extremely good tutorial supplied by Pebble.

I chose to write in C because I’m old, although there is a javascript compiler too for you younger developers who aren’t snooty about strongly typed languages like me. The best thing is this is proper C. Pointers are your friend. If you don’t know why variables are declared with an asterisk in front of them, you might want to read up on Pointers before starting. Also memory is at a premium on Pebble, as you might imagine, so get into the habit of writing the code to destroy variables before declaring them – it will save you a lot of heartache.

You will need a Pebble account to log into the development environment (found at http://www.cloudpebble.net), however the IDE includes an emulator so you can create an account, have a bash and see if you like it. The compiler  gives reasonable feedback too.

Fonts and bitmaps are loaded as resources within the project. Once uploaded they are called up using resource names, which makes resource management a doddle. There are lots of options when uploading, I’ve not explored them fully, but other than knowing some simple Regular Expressions declarations (for limiting the characters loaded in from the font) it’s all done from drop downs and checkboxes so is simple to use. The IDE also links direct to GitHub so sharing your code is also a piece of cake. Mmmm cake.

To get your design on to your watch you need to enable Developer Connection from your phone. This allows direct IP connection from the IDE to your phone’s Pebble app and then on to your Pebble via bluetooth.

Simple Pebble Watchface

Simple Pebble Watchface

All in all it’s really easy to get started writing an app for the Pebble smartwatch SDK, and shouldn’t be too much of a problem for someone with some experience playing with Arduinos to get started with.

Here’s the result of my first play, and below that the code itself. If you want to know more or have an indepth look, grab me at the hackspace, leave a comment below or see me at the biweekly Oldham CodeUp meetings, starting on 15-Jun-2017 at HackOldham, 38-44 Yorkshire Steet, Oldham.

 

 

 

 

 


 

#include <pebble.h>

static Window *s_main_window; //Clockface container

static TextLayer *s_time_layer; //Text layer to display time

static GFont s_time_font; //Font container (any TTF can be uploaded)

static BitmapLayer *s_background_layer; //Container for background image on display

static GBitmap *s_background_bitmap; //Container for bitmap file (well, png)



//Runs whenever window (main container) loads

static void main_window_load(Window *window){

 //Assign window container and set bounds

 Layer *window_layer = window_get_root_layer(window); 

 GRect bounds = layer_get_bounds(window_layer);

 

 //Load background bitmap, define layer, assign to background and add layer to window

 //NOTE: DO THIS BEFORE DOING TIME TEXT LAYER, TIME TEXT MUST BE DONE LAST

 s_background_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_HACKOLDHAM);

 s_background_layer = bitmap_layer_create(bounds);

 bitmap_layer_set_bitmap(s_background_layer, s_background_bitmap);

 layer_add_child(window_layer, bitmap_layer_get_layer(s_background_layer));

 

 //Load time font

 s_time_font = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_DRIPPING_MARKER_48));



 //Create time text layer, set params and assign font

 s_time_layer = text_layer_create(

 GRect(0, PBL_IF_ROUND_ELSE(58,52), bounds.size.w, 50)

 );

 text_layer_set_background_color(s_time_layer, GColorClear);

 text_layer_set_text_color(s_time_layer, GColorRed);

 text_layer_set_font(s_time_layer, s_time_font);

 text_layer_set_text_alignment(s_time_layer, GTextAlignmentCenter);

 

 layer_add_child(window_layer, text_layer_get_layer(s_time_layer));

 

}



//Runs whenever window is unloaded (switching apps etc...)

static void main_window_unload(Window *window){

 gbitmap_destroy(s_background_bitmap); //Destroy bitmap

 bitmap_layer_destroy(s_background_layer); //Destroy background layer

 fonts_unload_custom_font(s_time_font); //Unload font

 text_layer_destroy(s_time_layer); //Destroy time text layer

}



//Called whenever time changes

static void update_time() {

 time_t temp = time(NULL); //Build a time structure (see documentation)

 struct tm *tick_time = localtime(&temp);

 

 static char s_buffer[8]; //Write the current hours and minutes into a buffer

 strftime(s_buffer, sizeof(s_buffer), "%H:%M", tick_time); //Note: 12h clock style is %I:%M



 text_layer_set_text(s_time_layer, s_buffer); //Display time on text layer

}



//Handler for time changing events

static void tick_handler(struct tm *tick_time, TimeUnits units_changed) {

 update_time();

}



//Runs whenever program starts 

static void init(){

 s_main_window = window_create(); //create window

 window_set_window_handlers(s_main_window, (WindowHandlers) { //register event handlers

 .load = main_window_load, .unload = main_window_unload

 });

 tick_timer_service_subscribe(MINUTE_UNIT, tick_handler); //Subscription for tick event handler

 window_set_background_color(s_main_window, GColorWhite);

 window_stack_push(s_main_window, true); //push window to stack (animate is true)

 update_time();

}



//Runs whenever program finishes

static void deinit(){

 window_destroy(s_main_window); //Destroy window container

}



//Main program

int main(void){

 init();

 app_event_loop();

 deinit();

}

 

 

 

 

No Comments

Post A Comment