Slide 1

Slide 1 text

Pebble Watch Development First Glance

Slide 2

Slide 2 text

What is Pebble? Teaser: https://youtu.be/8d2PpY_qrVQ Unpacking: https://www.youtube.com/watch?v=5Ajh 7NFxolk

Slide 3

Slide 3 text

Watch types

Slide 4

Slide 4 text

Watch types

Slide 5

Slide 5 text

Watch types

Slide 6

Slide 6 text

Pebble Developer Portal https://developer.pebble.com ● Instructions for CloudPebble and SDK ● C Language ● Android and iOS SDKs ● Guides, examples, blog

Slide 7

Slide 7 text

Emulators

Slide 8

Slide 8 text

CloudPebble https://cloudpebble.net/ide/ https://developer.pebble.com/guides/t ools-and-resources/cloudpebble/

Slide 9

Slide 9 text

New Cloud Project Project types available: ● Pebble C SDK ● Simple.js ● Pebble.js (beta) SDK versions available: 2 and 3. Templates: ● Empty project ● Minimal ● ButtonClick ● HelloWorld ● AppMessage

Slide 10

Slide 10 text

Import Project ● From GitHub ● From .zip

Slide 11

Slide 11 text

CloudPebble IDE ● Editor ● Emulator ● Save button

Slide 12

Slide 12 text

Settings

Slide 13

Slide 13 text

Sensors emulation

Slide 14

Slide 14 text

Run Build

Slide 15

Slide 15 text

User Settings

Slide 16

Slide 16 text

Cloud Build

Slide 17

Slide 17 text

Cloud Emulator

Slide 18

Slide 18 text

Controls

Slide 19

Slide 19 text

Controls

Slide 20

Slide 20 text

UI Editor - build layout code with WSIWYG

Slide 21

Slide 21 text

Pebble SDK (with QEMU Based emulator) https://developer.pebble.com/sdk/install/mac/ https://developer.pebble.com/sdk / brew install pebble/pebble-sdk/pebble-sdk

Slide 22

Slide 22 text

Run standalone emulator pebble install --emulator basalt

Slide 23

Slide 23 text

Documentation https://developer.pebble.com/guides/tools-and-resources/pebble-tool /

Slide 24

Slide 24 text

iOS and Android SDKs https://github.com/pebble/pebble-ios-sdk/ CocoaPods and Carthage supported https://github.com/pebble/pebble-android-sdk/ Gradle, Maven and jar available

Slide 25

Slide 25 text

Development

Slide 26

Slide 26 text

App structure ● main() function ● app_event_loop() is mandatory ● init() and deinit() are optional

Slide 27

Slide 27 text

Window ● Window type ● window_stack_push() to display

Slide 28

Slide 28 text

TextLayer ● Has coordinates ● Need to be added to window

Slide 29

Slide 29 text

TextLayer formatting

Slide 30

Slide 30 text

WatchFace TickTimerService Register with TickTimerService: static void tick_handler(struct tm *tick_time, TimeUnits units_changed) {...} tick_timer_service_subscribe(MINUTE_UNIT, tick_handler);

Slide 31

Slide 31 text

Other example of plain old C

Slide 32

Slide 32 text

Customizations ● Add resources to appinfo.json, in array media ● Use GFont for TextLayer custom fonts ● Use GBitmap for BitmapLayer ● Use create_with_resource for loading resources ● Use _destroy functions to free resources

Slide 33

Slide 33 text

Limitations ● Number of resources - 256 ● Max resource size - 128kB (Aplite), 256kB (Basalt and Chalk)

Slide 34

Slide 34 text

Worker 1 worker = 1 app worker_launch_app() app_launch_worker() Worker_src Storage API, AppWorkerMessage (send, subscribe)

Slide 35

Slide 35 text

Event Services https://developer.pebble.com/docs/c/Foundation/Event_Service/ https://developer.pebble.com/guides/events-and-services/events/ Handler may listen for event, or use “peek” style to read single data from API ● AppFocusService ● AccelerometerService ● BatteryStateService ● ConnectionService ● HealthService ● TickTimerService

Slide 36

Slide 36 text

HealthService AppInfo.json - add ["capabilities": [ "health" ]

Slide 37

Slide 37 text

Publishing: Register your App https://dev-portal.getpebble.com/

Slide 38

Slide 38 text

Publishing: Category

Slide 39

Slide 39 text

Dictation

Slide 40

Slide 40 text

Storage API Limited to 4KB persist_write_data(key, &data, sizeof(Data)); persist_read_data(key, &data, sizeof(Data)); Alternative - localStorage API in PebbleKit JS. But it’s not battery efficient And depends on connection between Watch and Phone

Slide 41

Slide 41 text

Wakeups Schedule app wakeups

Slide 42

Slide 42 text

Communication

Slide 43

Slide 43 text

PebbleKit JS ● Access to extended storage with localStorage. ● Internet access using XMLHttpRequest. ● Location data using geolocation. ● The ability to show a configuration page to allow users to customize how the app behaves.

Slide 44

Slide 44 text

AppMessage API Bi-directional communication between phone apps and Pebble watchapps. ACKnowledged or "NACK'ed," app_message_open() APP_MESSAGE_INBOX_SIZE_MINIMUM and APP_MESSAGE_OUTBOX_SIZE_MINIMUM app_message_inbox_size_maximum() and app_message_outbox_size_maximum()

Slide 45

Slide 45 text

Companion Apps

Slide 46

Slide 46 text

PebbleKit Android dependencies { compile 'com.getpebble:pebblekit:3.0.0' } PebbleDictionary dict = new PebbleDictionary(); dict.addString(AppKeyContactName, contactName); final UUID appUuid = UUID.fromString("EC7EE5C6-8DDF-4089-AA84-C3396A11CC95"); // Send the dictionary PebbleKit.sendDataToPebble(getApplicationContext(), appUuid, dict);

Slide 47

Slide 47 text

PebbleKit Android Messages will be received on Pebble Watch in: AppMessageInboxReceived PebbleKit.registerReceivedDataHandler(getApplicationContext(), dataReceiver);

Slide 48

Slide 48 text

PebbleKit Android // Create a new receiver to get AppMessages from the C app PebbleDataReceiver dataReceiver = new PebbleDataReceiver(appUuid) { @Override public void receiveData(Context context, int transaction_id, PebbleDictionary dict) { // A new AppMessage was received, tell Pebble PebbleKit.sendAckToPebble(context, transaction_id); } };

Slide 49

Slide 49 text

PebbleKit Android @Override public void receiveData(Context context, int transaction_id, PebbleDictionary dict) { final int AppKeyAge = 1; // If the tuple is present... Long ageValue = dict.getInteger(AppKeyAge); if(ageValue != null) { // Read the integer value

Slide 50

Slide 50 text

PebbleKit Android startAppOnPebble() closeAppOnPebble() registerPebbleConnectedReceiver() registerPebbleDisconnectedReceiver()

Slide 51

Slide 51 text

PebbleKit iOS NSUUID *myAppUUID = [[NSUUID alloc] initWithUUIDString:@"226834ae-786e-4302-a52f-6e7efc9f990b"]; [PBPebbleCentral defaultCentral].appUUID = myAppUUID;

Slide 52

Slide 52 text

PebbleKit iOS @interface ViewController () central = [PBPebbleCentral defaultCentral]; central.appUUID = myAppUUID; [central run];

Slide 53

Slide 53 text

PebbleKit iOS [PBPebbleCentral defaultCentral].delegate = self; - (void)pebbleCentral:(PBPebbleCentral*)central watchDidConnect:(PBWatch*)watch isNew:(BOOL)isNew { NSLog(@"Pebble connected: %@", [watch name]); // Keep a reference to this watch self.connectedWatch = watch; }

Slide 54

Slide 54 text

PebbleKit iOS [[PBPebbleCentral defaultCentral] run];

Slide 55

Slide 55 text

PebbleKit iOS [self.connectedWatch appMessagesPushUpdate:update onSent:^(PBWatch *watch, NSDictionary *update, NSError *error) { if (!error) { NSLog(@"Successfully sent message."); } else { NSLog(@"Error sending message: %@", error); } }];

Slide 56

Slide 56 text

PebbleKit iOS [self.connectedWatch appMessagesAddReceiveUpdateHandler:^BOOL(PBWatch *watch, NSDictionary *update) { NSLog(@"Received message: %@", update); // Send Ack to Pebble return YES; }];

Slide 57

Slide 57 text

Publishing App

Slide 58

Slide 58 text

Pebble Marketplace

Slide 59

Slide 59 text

Immediate, easy, no validation

Slide 60

Slide 60 text

Only .PBW and icon - and you are in the market

Slide 61

Slide 61 text

Thank you! Constantine Mars @ConstantineMars +ConstantineMars rx.ConstantineMars [email protected]