pebble watch ios sdk overview

Post on 28-Jan-2015

112 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Pebble is the first watch built for the 21st century. It is very minimal yet extremely customizable with internet-connected apps. During this session we will look at the technical capabilities of the Pebble and what you can achieve when you connect your iPhone to it. By the end of the session you will know how to take your iOS knowledge and build great Pebble apps.

TRANSCRIPT

Pebble Watchmatthewmorey.com | @xzolian

matthewmorey.com | @xzolian

http://buoyexplorer.com

☐ What is the Pebble☐ Why you should develop for the Pebble☐ How to develop for the Pebble

Agenda

Demo

vs

ARM Cortex-M3 MCU 120 MHz

Apple A6ARMv7 1.3 GHz

Dual Core

128 KB RAMUp to 8 apps

1 GB RAMUp to 64 GB storage

144 x 168 pixels1-bit color“e-paper”

1,136 × 640 pixels24-bit Color

“Retina”

Pebble iPhone 5

CPU

Memory

Screen

Bluetooth 2.1 and 4.0 LE

Bluetooth 4.0802.11a/b/g/n Wi-Fi

Cellular LTE

3-axis accelerometerAmbient light

Magnetometer

Three-axis gyroAccelerometer

Proximity sensorAmbient light sensor

4 buttonsVibration

Screen backlight

Touch screenButtons

VibrationCamera

Pebble iPhone 5

Comm.

Sensors

IO

2 to 14 days ~1 day

FreeRTOSPebble SDK

PebbleKit

iOSiOS SDK

5 ATM water resistance

22 mm watch band

Not water resistantCan’t wear on wrist

Pebble iPhone 5

Battery

Software

Other

Issues

☑ What is the Pebble☐ Why you should develop for the Pebble☐ How to develop for the Pebble

Agenda

LunaTik

“I agree to wear you around and share a lot of personal data

with you.”

- Customers

$10,266,846 - Pebble Watch (design)

$8,596,475 - OUYA (Android console)

$5,702,153 - Veronica Mars (movie)

$4,188,927 - Torment: Tides of Numenera (game)

$3,986,929 - Project Eternity (game)

$6 Billionper year

Units Sold

Pebble iPhone

>100,000

>250 Million

iOS 7

☑ What is the Pebble☑ Why you should develop for the Pebble☐ How to develop for the Pebble

Agenda

Pebble SDK

1. Pebble SDK dependencies2. Pebble SDK3. ARM dependencies4. Pebble ARM toolchain

Install

Hello World

$ create_pebble_project.py \ > PebbleSDK-1.12/Pebble/sdk \ > hello_world

1 #include "pebble_os.h" 2 #include "pebble_app.h" 3 #include "pebble_fonts.h" 4 5 #define MY_UUID { 6 0x20, 0xD9, 0xFB, 0x8F, 0xBE, 0xCF, 0x49, 7 0x94, 0xA9, 0xE8, 0x70, 0xC0, 0xEA, 0xC6, 8 0x50, 0x16 9 }10 11 PBL_APP_INFO(12 MY_UUID,13 "Hello World",14 "Acme Corp",15 1, 0, /* App version */16 DEFAULT_MENU_ICON,17 APP_INFO_STANDARD_APP18 );

1 #include "pebble_os.h" 2 #include "pebble_app.h" 3 #include "pebble_fonts.h" 4 5 #define MY_UUID { 6 0x20, 0xD9, 0xFB, 0x8F, 0xBE, 0xCF, 0x49, 7 0x94, 0xA9, 0xE8, 0x70, 0xC0, 0xEA, 0xC6, 8 0x50, 0x16 9 }10 11 PBL_APP_INFO(12 MY_UUID,13 "Hello World",14 "Acme Corp",15 1, 0, /* App version */16 DEFAULT_MENU_ICON,17 APP_INFO_STANDARD_APP18 );

1 #include "pebble_os.h" 2 #include "pebble_app.h" 3 #include "pebble_fonts.h" 4 5 #define MY_UUID { 6 0x20, 0xD9, 0xFB, 0x8F, 0xBE, 0xCF, 0x49, 7 0x94, 0xA9, 0xE8, 0x70, 0xC0, 0xEA, 0xC6, 8 0x50, 0x16 9 }10 11 PBL_APP_INFO(12 MY_UUID,13 "Hello World",14 "Acme Corp",15 1, 0, /* App version */16 DEFAULT_MENU_ICON,17 APP_INFO_STANDARD_APP18 );

20 Window window;21 22 void handle_init(AppContextRef ctx) {23 window_init(&window, "Window Name");24 window_stack_push(&window,true/*Animated*/);25 }26 27 28 void pbl_main(void *params) {29 PebbleAppHandlers handlers = {30 .init_handler = &handle_init31 };32 app_event_loop(params, &handlers);33 }

20 Window window;21 22 void handle_init(AppContextRef ctx) {23 window_init(&window, "Window Name");24 window_stack_push(&window,true/*Animated*/);25 }26 27 28 void pbl_main(void *params) {29 PebbleAppHandlers handlers = {30 .init_handler = &handle_init31 };32 app_event_loop(params, &handlers);33 }

20 Window window;21 22 void handle_init(AppContextRef ctx) {23 window_init(&window, "Window Name");24 window_stack_push(&window,true/*Animated*/);25 }26 27 28 void pbl_main(void *params) {29 PebbleAppHandlers handlers = {30 .init_handler = &handle_init31 };32 app_event_loop(params, &handlers);33 }

20 Window window;21 22 void handle_init(AppContextRef ctx) {23 window_init(&window, "Window Name");24 window_stack_push(&window,true/*Animated*/);25 }26 27 28 void pbl_main(void *params) {29 PebbleAppHandlers handlers = {30 .init_handler = &handle_init31 };32 app_event_loop(params, &handlers);33 }

15 TextLayer hello_layer;16 17 void handle_init(AppContextRef ctx) {18 19 window_init(&window, "Window Name");20 window_stack_push(&window, true /* Animated */);21 22 text_layer_init(&hello_layer, GRect(0, 65, 144, 30));23 text_layer_set_text_alignment(&hello_layer,GTextAlignmentCenter);24 text_layer_set_text(&hello_layer, "Hello World!");25 text_layer_set_font(26 &hello_layer,27 fonts_get_system_font(FONT_KEY_ROBOTO_CONDENSED_21)28 );2930 layer_add_child(&window.layer, &hello_layer.layer);31 32 }

15 TextLayer hello_layer;16 17 void handle_init(AppContextRef ctx) {18 19 window_init(&window, "Window Name");20 window_stack_push(&window, true /* Animated */);21 22 text_layer_init(&hello_layer, GRect(0, 65, 144, 30));23 text_layer_set_text_alignment(&hello_layer,GTextAlignmentCenter);24 text_layer_set_text(&hello_layer, "Hello World!");25 text_layer_set_font(26 &hello_layer,27 fonts_get_system_font(FONT_KEY_ROBOTO_CONDENSED_21)28 );2930 layer_add_child(&window.layer, &hello_layer.layer);31 32 }

$ ./waf configure$ ./waf build$ python -m SimpleHTTPServer 8000

$ ./waf configure$ ./waf build$ python -m SimpleHTTPServer 8000

Demo

PBW Filehello_world.pbw (zip archive)

app_resources.pbpack (binary)

manifest.json (txt/json)

pebble-app.bin (binary)

App Watch Face

Sports Apps

Event Handlers

On-screen Layers

Resources

Window Stack

View Lifecycle

load

appear

disappear

unload

viewDidLoad

viewWillAppear

viewDidAppear

viewWillDisappear

viewDidDisappear

Pebble iOS

Layers

Layers10

Layers20

10

Frame

Layers

20

20

Frame

Layers

-100

Bounds

Layers

60

20

Bounds

animation_init() ...animation_schedule()

.update called

.update called ....update called

Animation scheduled

.stopped called

App Pebble OS

Animation

Animation stopped

.started called

Input Handlers

Resourcesraw

png

png-trans

font

Debuggingapp_log

vibes_short_pulsevibes_double_pulsevibes_long_pulse

light_enable_interaction

Watch <=> Phone

app_message_out_send() Dictionary

ACK .out_sent calledAccepted

app_message_out_send() Dictionary

NACK .out_failed calledRejected

Pebble Phone

AppMessage

.in_received called Dictionary

ACK

Sending

Pebble Phone

AppMessage

.in_received called Dictionary

NACK

Sending

app_sync_set(...)

tuple_changed

Accepted

Sending

Pebble Phone

AppSync

190 - (void)setTargetWatch:(PBWatch*)watch {191 192 self.watch = watch;193 194 // Test if the Pebble's firmware supports AppMessages195 [watch appMessagesGetIsSupported: ^(PBWatch *watch, BOOL isAppMessagesSupported) {196197 if (isAppMessagesSupported) {198 199 // Configure communications channel to target the weather app:200 uint8_t bytes[] = {201 0x42, 0xc8, 0x6e, 0xa4, 0x1c, 0x3e, 0x4a, 0x07, 202 0xb8, 0x89, 0x2c, 0xcc, 0xca, 0x91, 0x41, 0x98};203 NSData *uuid = [NSData dataWithBytes:bytes length:sizeof(bytes)];204 [watch appMessagesSetUUID:uuid];205 206 [self updateWatch];207 208 } 209210 }];211 } iOS

190 - (void)setTargetWatch:(PBWatch*)watch {191 192 self.watch = watch;193 194 // Test if the Pebble's firmware supports AppMessages195 [watch appMessagesGetIsSupported: ^(PBWatch *watch, BOOL isAppMessagesSupported) {196197 if (isAppMessagesSupported) {198 199 // Configure communications channel to target the weather app:200 uint8_t bytes[] = {201 0x42, 0xc8, 0x6e, 0xa4, 0x1c, 0x3e, 0x4a, 0x07, 202 0xb8, 0x89, 0x2c, 0xcc, 0xca, 0x91, 0x41, 0x98};203 NSData *uuid = [NSData dataWithBytes:bytes length:sizeof(bytes)];204 [watch appMessagesSetUUID:uuid];205 206 [self updateWatch];207 208 } 209210 }];211 } iOS

190 - (void)setTargetWatch:(PBWatch*)watch {191 192 self.watch = watch;193 194 // Test if the Pebble's firmware supports AppMessages195 [watch appMessagesGetIsSupported: ^(PBWatch *watch, BOOL isAppMessagesSupported) {196197 if (isAppMessagesSupported) {198 199 // Configure communications channel to target the weather app:200 uint8_t bytes[] = {201 0x42, 0xc8, 0x6e, 0xa4, 0x1c, 0x3e, 0x4a, 0x07, 202 0xb8, 0x89, 0x2c, 0xcc, 0xca, 0x91, 0x41, 0x98};203 NSData *uuid = [NSData dataWithBytes:bytes length:sizeof(bytes)];204 [watch appMessagesSetUUID:uuid];205 206 [self updateWatch];207 208 } 209210 }];211 } iOS

259 - (void)updateWatch {260 261 NSDictionary *update = @{262 kKeyWatchIcon:[NSNumber numberWithUint8:1],263 kKeyWatchTemperature:[NSString stringWithFormat:@"%.1f \u00B0F", @”90”]264 };265 266 [self.watch appMessagesPushUpdate:update onSent: ^(PBWatch *watch, NSDictionary *update, NSError *error) {267 268 if (error) {269 // Message was not sent270 } else {271 // Message was sent272 }273 274 }];275 276 }

iOS

259 - (void)updateWatch {260 261 NSDictionary *update = @{262 kKeyWatchIcon:[NSNumber numberWithUint8:1],263 kKeyWatchTemperature:[NSString stringWithFormat:@"%.1f \u00B0F", @”90”]264 };265 266 [self.watch appMessagesPushUpdate:update onSent: ^(PBWatch *watch, NSDictionary *update, NSError *error) {267 268 if (error) {269 // Message was not sent270 } else {271 // Message was sent272 }273 274 }];275 276 }

iOS

259 - (void)updateWatch {260 261 NSDictionary *update = @{262 kKeyWatchIcon:[NSNumber numberWithUint8:1],263 kKeyWatchTemperature:[NSString stringWithFormat:@"%.1f \u00B0F", @”90”]264 };265 266 [self.watch appMessagesPushUpdate:update onSent: ^(PBWatch *watch, NSDictionary *update, NSError *error) {267 268 if (error) {269 // Message was not sent270 } else {271 // Message was sent272 }273 274 }];275 276 }

iOS

296 - (BOOL)handleWatchUpdate:(PBWatch *)watch message:(NSDictionary *)message {299 300 if ([message objectForKey:kKeyWatchRequestUpdate]) {301 NSLog(@"Forecast update requested");303 return YES;304 }305 306 return NO;307 308 }

402 self.updateHandler = [self.watch appMessagesAddReceiveUpdateHandler: ^BOOL(PBWatch *watch, NSDictionary *update) {403 return [self handleWatchUpdate:watch message:update];404 }];

iOS

296 - (BOOL)handleWatchUpdate:(PBWatch *)watch message:(NSDictionary *)message {299 300 if ([message objectForKey:kKeyWatchRequestUpdate]) {301 NSLog(@"Forecast update requested");303 return YES;304 }305 306 return NO;307 308 }

402 self.updateHandler = [self.watch appMessagesAddReceiveUpdateHandler: ^BOOL(PBWatch *watch, NSDictionary *update) {403 return [self handleWatchUpdate:watch message:update];404 }];

iOS

296 - (BOOL)handleWatchUpdate:(PBWatch *)watch message:(NSDictionary *)message {299 300 if ([message objectForKey:kKeyWatchRequestUpdate]) {301 NSLog(@"Forecast update requested");303 return YES;304 }305 306 return NO;307 308 }

402 self.updateHandler = [self.watch appMessagesAddReceiveUpdateHandler: ^BOOL(PBWatch *watch, NSDictionary *update) {403 return [self handleWatchUpdate:watch message:update];404 }];

iOS

171 void pbl_main(void *params) {172 173 PebbleAppHandlers handlers = {174 175 .init_handler = &app_init,176 .deinit_handler = &app_deinit,177 .messaging_info = {178 .buffer_sizes = {179 .inbound = 64,180 .outbound = 16,181 }182 },183 // Handle time updates184 .tick_info = {185 .tick_handler = &handle_minute_tick,186 .tick_units = MINUTE_UNIT187 }188 };189 190 app_event_loop(params, &handlers);191 192 }

Pebble

171 void pbl_main(void *params) {172 173 PebbleAppHandlers handlers = {174 175 .init_handler = &app_init,176 .deinit_handler = &app_deinit,177 .messaging_info = {178 .buffer_sizes = {179 .inbound = 64,180 .outbound = 16,181 }182 },183 // Handle time updates184 .tick_info = {185 .tick_handler = &handle_minute_tick,186 .tick_units = MINUTE_UNIT187 }188 };189 190 app_event_loop(params, &handlers);191 192 }

Pebble

171 void pbl_main(void *params) {172 173 PebbleAppHandlers handlers = {174 175 .init_handler = &app_init,176 .deinit_handler = &app_deinit,177 .messaging_info = {178 .buffer_sizes = {179 .inbound = 64,180 .outbound = 16,181 }182 },183 // Handle time updates184 .tick_info = {185 .tick_handler = &handle_minute_tick,186 .tick_units = MINUTE_UNIT187 }188 };189 190 app_event_loop(params, &handlers);191 192 }

Pebble

171 void pbl_main(void *params) {172 173 PebbleAppHandlers handlers = {174 175 .init_handler = &app_init,176 .deinit_handler = &app_deinit,177 .messaging_info = {178 .buffer_sizes = {179 .inbound = 64,180 .outbound = 16,181 }182 },183 // Handle time updates184 .tick_info = {185 .tick_handler = &handle_minute_tick,186 .tick_units = MINUTE_UNIT187 }188 };189 190 app_event_loop(params, &handlers);191 192 }

Pebble

171 void pbl_main(void *params) {172 173 PebbleAppHandlers handlers = {174 175 .init_handler = &app_init,176 .deinit_handler = &app_deinit,177 .messaging_info = {178 .buffer_sizes = {179 .inbound = 64,180 .outbound = 16,181 }182 },183 // Handle time updates184 .tick_info = {185 .tick_handler = &handle_minute_tick,186 .tick_units = MINUTE_UNIT187 }188 };189 190 app_event_loop(params, &handlers);191 192 }

Pebble

116 static void app_init(AppContextRef c) {117118 resource_init_current_app(&WEATHER_APP_RESOURCES);119 120 Window* window = &s_data.window;121 window_init(window, "PebbleWeather");122 window_set_background_color(window, GColorBlack);123 window_set_fullscreen(window, true);124

...149 // Watch <--> Phone communication150 Tuplet initial_values[] = {151 TupletInteger(WEATHER_ICON_KEY, (uint8_t) 1),152 TupletCString(WEATHER_TEMPERATURE_KEY, "-\u00B0C"),153 };154 app_sync_init(&s_data.sync, s_data.sync_buffer, sizeof(s_data.sync_buffer), initial_values, ARRAY_LENGTH(initial_values), sync_tuple_changed_callback, sync_error_callback, NULL);155 156 window_stack_push(window, true);157 168 } Pebble

116 static void app_init(AppContextRef c) {117118 resource_init_current_app(&WEATHER_APP_RESOURCES);119 120 Window* window = &s_data.window;121 window_init(window, "PebbleWeather");122 window_set_background_color(window, GColorBlack);123 window_set_fullscreen(window, true);124

...149 // Watch <--> Phone communication150 Tuplet initial_values[] = {151 TupletInteger(WEATHER_ICON_KEY, (uint8_t) 1),152 TupletCString(WEATHER_TEMPERATURE_KEY, "-\u00B0C"),153 };154 app_sync_init(&s_data.sync, s_data.sync_buffer, sizeof(s_data.sync_buffer), initial_values, ARRAY_LENGTH(initial_values), sync_tuple_changed_callback, sync_error_callback, NULL);155 156 window_stack_push(window, true);157 168 } Pebble

116 static void app_init(AppContextRef c) {117118 resource_init_current_app(&WEATHER_APP_RESOURCES);119 120 Window* window = &s_data.window;121 window_init(window, "PebbleWeather");122 window_set_background_color(window, GColorBlack);123 window_set_fullscreen(window, true);124

...149 // Watch <--> Phone communication150 Tuplet initial_values[] = {151 TupletInteger(WEATHER_ICON_KEY, (uint8_t) 1),152 TupletCString(WEATHER_TEMPERATURE_KEY, "-\u00B0C"),153 };154 app_sync_init(&s_data.sync, s_data.sync_buffer, sizeof(s_data.sync_buffer), initial_values, ARRAY_LENGTH(initial_values), sync_tuple_changed_callback, sync_error_callback, NULL);155 156 window_stack_push(window, true);157 168 } Pebble

116 static void app_init(AppContextRef c) {117118 resource_init_current_app(&WEATHER_APP_RESOURCES);119 120 Window* window = &s_data.window;121 window_init(window, "PebbleWeather");122 window_set_background_color(window, GColorBlack);123 window_set_fullscreen(window, true);124

...149 // Watch <--> Phone communication150 Tuplet initial_values[] = {151 TupletInteger(WEATHER_ICON_KEY, (uint8_t) 1),152 TupletCString(WEATHER_TEMPERATURE_KEY, "-\u00B0C"),153 };154 app_sync_init(&s_data.sync, s_data.sync_buffer, sizeof(s_data.sync_buffer), initial_values, ARRAY_LENGTH(initial_values), sync_tuple_changed_callback, sync_error_callback, NULL);155 156 window_stack_push(window, true);157 168 } Pebble

104 // Send message to phone asking for a weather update105 void request_weather_update() {106 107 vibes_double_pulse();108 109 Tuplet values[] = {110 TupletInteger(WEATHER_FORECAST_REQUEST_KEY, 1),111 };112 app_sync_set(&s_data.sync, values, ARRAY_LENGTH(values));113 114 }

Pebble

104 // Send message to phone asking for a weather update105 void request_weather_update() {106 107 vibes_double_pulse();108 109 Tuplet values[] = {110 TupletInteger(WEATHER_FORECAST_REQUEST_KEY, 1),111 };112 app_sync_set(&s_data.sync, values, ARRAY_LENGTH(values));113 114 }

Pebble

65 // Tuple changed 66 static void sync_tuple_changed_callback( const uint32_t key, const Tuple* new_tuple, const Tuple* old_tuple, void* context) { 67 68 switch (key) { 69 case WEATHER_ICON_KEY: 70 load_bitmap(WEATHER_ICONS[new_tuple->value->uint8]); 71 bitmap_layer_set_bitmap( &s_data.icon_layer, &s_data.icon_bitmap.bmp ); 72 break; 73 74 case WEATHER_TEMPERATURE_KEY: 75 text_layer_set_text( &s_data.temperature_layer, new_tuple->value->cstring ); 76 break; 77 78 default: 79 return; 80 } 81 } Pebble

65 // Tuple changed 66 static void sync_tuple_changed_callback( const uint32_t key, const Tuple* new_tuple, const Tuple* old_tuple, void* context) { 67 68 switch (key) { 69 case WEATHER_ICON_KEY: 70 load_bitmap(WEATHER_ICONS[new_tuple->value->uint8]); 71 bitmap_layer_set_bitmap( &s_data.icon_layer, &s_data.icon_bitmap.bmp ); 72 break; 73 74 case WEATHER_TEMPERATURE_KEY: 75 text_layer_set_text( &s_data.temperature_layer, new_tuple->value->cstring ); 76 break; 77 78 default: 79 return; 80 } 81 } Pebble

65 // Tuple changed 66 static void sync_tuple_changed_callback( const uint32_t key, const Tuple* new_tuple, const Tuple* old_tuple, void* context) { 67 68 switch (key) { 69 case WEATHER_ICON_KEY: 70 load_bitmap(WEATHER_ICONS[new_tuple->value->uint8]); 71 bitmap_layer_set_bitmap( &s_data.icon_layer, &s_data.icon_bitmap.bmp ); 72 break; 73 74 case WEATHER_TEMPERATURE_KEY: 75 text_layer_set_text( &s_data.temperature_layer, new_tuple->value->cstring ); 76 break; 77 78 default: 79 return; 80 } 81 } Pebble

☑ What is the Pebble☑ Why you should develop for the Pebble☑ How to develop for the Pebble

Agenda

Questions?

matthewmorey.com | @xzolian

CreditsPicturesPebble, Pebble Forums, Pebble SubReddit, iFixIt, Wired, Verge, Lifehacker, BBC, MyPebbleFaces, Kickstarter, indiegogo, Wikipedia

top related