Pebble SDK 2.0 is a brand new SDK for the Pebble smartwatch with support for JavaScript enabled apps, accelerometer, persistent storage, new tools, etc.
You can also watch the video announcement:
http://www.youtube.com/watch?v=uoVX2ibCFXw&feature=youtu.be
3. Introducing Pebble SDK 2.0
If you are watching live, you can ask questions
On our IRC channel: #pebble on irc.freenode.net
During our AMA on Reddit at 12pm PST today
This is recorded and will be available on our YouTube channel and on
the developer web site
Friendly warning: This presentation is mostly intended for developers
4. New Tools
Improving the developer experience
CloudPebble
Simplified build system
Deploying from the command line
Application logs
Documentation
10. New Tools
Developer Connection
$ export PEBBLE_PHONE=192.168.1.42
$ pebble install --logs
[INFO
[INFO
[INFO
[INFO
]
]
]
]
Installation successful
Enabling application logging...
Displaying logs ... Ctrl-C to interrupt.
D helloworld.c:58 Done initializing
A very simple and reliable way to install and watch log messages
11. New Tools
Documentation
We have re-written almost all of Pebble Documentation
Pebble documentation now includes:
• A Getting Started Guide
• Pebble Developer Guide with 11 chapters
• Pebble Mobile Developer Guide
• Pebble 2.0 Migration Guide
• API Reference for Pebble, iOS and Android
12. New Tools
Improving the developer experience
CloudPebble
Simplified build system
Deploying from the command line
Application logs
Documentation
14. SDK Overhaul
Migrating to Pebble 2.0
Pebble 2.0 is a major evolution of Pebble 1.0 with lots of changes in the
system and in the SDK
• Pebble 2.0 is not compatible with 1.0 apps
• Developers need to migrate their application to Pebble 2.0
Refer to Pebble 2.0 Migration Guide
http://developer.getpebble.com/2/guides/migration-guide.html
15. SDK Overhaul
Pebble application must
provide some metadata
through a JSON file in the
project called appinfo.json
• Application name
• UUID
• Watchface / Watchapp
• Resources
• etc
Application metadata
16. SDK Overhaul
Using pointers and dynamic memory
In Pebble OS 2.0, all the SDK structures are opaque. This means we can
change them without you having to recompile your apps.
You cannot allocate structures as global variables as you did in 1.0. You
must use pointers and memory allocated dynamically by the system.
All calls to _init() functions become are replaced by _create() calls
Window my_window;
window_init(&my_window);
becomes
Window *my_window;
my_window = window_create();
17. SDK Overhaul
Getting closer to standards: C/UNIX
• pbl_main() is now called main()
• PblTm is replaced by struct tm
• string_format_time() is replaced by strftime()
• Pebble does not support timezones yet but we introduce gmtime()
and localtime() to prepare for timezone support.
• get_time() is replaced by localtime(time(NULL))
18. SDK Overhaul
Enforcing a subscription based Event system
Pebble 2.0 relies heavily on Events. You register to events with
_register functions.
All Pebble 1.x APIs have been updated: Timer, Tick, AppMessage, etc
PebbleAppHandlers handlers = {
.timer_handler = &handle_timer
};
becomes
timer = app_timer_register(1500, timer_callback, NULL);
19. SDK Overhaul
Dynamic Memory
Introducing two old friends: malloc() and free()
Each application has it’s own heap and is cleaned automatically
You can attach data to layers and windows (layer_create_with_data()
and window_set_user_data())
Your total memory is ~24k. Your heap space is 24k minus app size.
Pebble SDK includes tool to help you manage your memory:
$ pebble build
Memory usage:
=============
Total app footprint in RAM:
822 bytes / ~24kb
Free RAM available (heap):
23754 bytes
!
$ pebble logs
...
[INFO
] I Heap Usage for <Template App>: Available <23200B> Used <2344B> Still allocated <0B>
20. SDK Overhaul
Migration in a nutshell
Use pebble convert-project to generate the new appinfo.json file
Rename pbl_main() into main()
Use pointers to structures instead of statically allocated structures
Use the SDK APIs to allocate memory and initialize the structs
Check the other APIs for changes
Refer to Pebble 2.0 Migration Guide
http://developer.getpebble.com/2/guides/migration-guide.html
23. New Frameworks
Event Services
The App Focus Service lets you know when your app is covered by a
modal window
typedef void (*AppFocusHandler)(bool in_focus);
!
void app_focus_service_subscribe(AppFocusHandler handler);
void app_focus_service_unsubscribe();
24. New Frameworks
Event Services
The Bluetooth Connection Service lets you know when the watch is
connected to the phone
typedef void (*BluetoothConnectionHandler)(bool connected);
void bluetooth_connection_service_subscribe(BluetoothConnectionHandler handler);
void bluetooth_connection_service_unsubscribe(void);
!
bool bluetooth_connection_service_peek(void);
25. New Frameworks
Event Services
The Battery State Service can let you know when the watch is plugged
or unplugged
typedef struct {
uint8_t charge_percent;
bool is_charging;
bool is_plugged;
} BatteryChargeState;
!
typedef void (*BatteryStateHandler)(BatteryChargeState charge);
void battery_state_service_subscribe(BatteryStateHandler handler);
void battery_state_service_unsubscribe();
!
void battery_state_service_peek(void);
26. New Frameworks
Event Services
A unique design pattern that communicates
with Pebble OS subsystems
Bluetooth, App Focus, Battery Status
Refer to Pebble 2.0 Event Services Guide
http://developer.getpebble.com/2/guides/event-service-guide.html
27. New Frameworks
Accelerometer
Let’s shake things up ...
The Accelerometer framework is designed with all use cases in mind:
user interaction for watchfaces, games, activity monitor, etc
29. New Frameworks
Accelerometer
The simplest way to use the accelerometer is to register for tap events
Those events are generated by the hardware and use very little energy
void accel_tap_handler(AccelAxisType axism int32_t direction) {
// Process tap on ACCEL_AXIS_X, ACCEL_AXIS_Y or ACCEL_AXIS_Z
}
!
void handle_init() {
accel_tap_service_subscribe(&accel_tap_handler);
}
!
void handle_deinit() { accel_tap_service_unsubscribe(); }
30. New Frameworks
Accelerometer
You can register to receive raw events one at a time
void accel_data_handler(AccelData *data, uint32_t num_samples) {
process_sample(&data);
}
!
void handle_init() {
accel_data_service_subscribe(1, &accel_data_handler);
}
!
void handle_deinit() { accel_data_service_unsubscribe(); }
31. New Frameworks
Accelerometer
The accelerometer API also supports storing samples on the hardware
void accel_data_handler(AccelData *data, uint32_t num_samples) {
// Process 10 events - every 1 second
}
!
void handle_init() {
accel_data_service_subscribe(10, &accel_data_handler);
accel_service_set_sampling_rate(ACCEL_SAMPLING_10HZ);
}
32. New Frameworks
Accelerometer
You can also peek at the accelerometer when updating your UI
This is the strategy we recommend for game developers
void tick_handler() {
AccelData data;
accel_service_peek(&data);
}
!
void handle_init() {
accel_data_service_subscribe(0, NULL);
}
void handle_deinit() { accel_data_service_unsubscribe(); };
33. New Frameworks
Accelerometer
The Accelerometer Service
Tap events - Regular measures - Batch processing - Real time processing
Refer to Pebble 2.0 Accelerometer Guide
http://developer.getpebble.com/2/guides/accelerometer.html
34. New Frameworks
Data Logging
A better way to transfer data
The data logging service is a transparent buffer between your watch
app and your phone that reliably and efficiently carries your data.
35. New Frameworks
Data Logging
Your watchapp creates one or multiple data logging sessions and
pushes data to those sessions.
Using PebbleKit iOS and Android, your mobile app gets events when
new data is available for download.
Your data is managed by Pebble OS: saved on the watch filesystem,
persisted if the user moves to another app, transferred in batches.
36. New Frameworks
Data Logging
You create a spool with a call to data_logging_create ()
DataSpoolRef my_data_spool;
!
void handle_init() {
logging_session = data_logging_create(
/* tag */
42,
/* data type */
DATA_LOGGING_BYTE_ARRAY,
/* length */
sizeof(AccelData),
/* resume */
true );
}
37. New Frameworks
Data Logging
Use data_logging_log() to add data to the spool
void accel_data_handler(AccelData *data, uint32_t num_samples) {
DataLoggingResult r = data_logging_log(logging_session, data, num_samples);
}
39. New Frameworks
Data Logging - iOS
You register to data spooling on iOS by providing a delegate to the
dataLoggingService
[[[PBPebbleCentral defaultCentral] dataLoggingService] setDelegate:self];
40. New Frameworks
Data Logging - iOS
The delegate implements methods to consume the data
- (BOOL)dataLoggingService:(PBDataLoggingService *)service
hasUInt32s:(const UInt32 [])data
numberOfItems:(UInt16)numberOfItems
forDataLoggingSession:(PBDataLoggingSessionMetadata *)sessionMetadata {
// Return YES when the data has been processed.
}
!
- (void)dataLoggingService:(PBDataLoggingService *)service
sessionDidFinish:(PBDataLoggingSessionMetadata *)sessionMetadata {
// Session closed.
}
41. New Frameworks
Data Logging
A better way to transfer data
The data logging service is a transparent buffer between your watch
app and your phone that reliably and efficiently carries your data.
Refer to the Ocean Data Survey example
Examples/data-logging-demo
42. New Frameworks
Persistent Storage
Store data on the watch
Persistent storage is perfect to save user settings, cache
data from the phone app, high scores, etc
43. New Frameworks
Persistent Storage
Every application get its own persistent storage space. Its size is limited
to 4kB.
Each value is associated to a uint32_t
key.
Persistent storage supports saving integers, strings and byte arrays.
The maximum size of byte arrays and strings is defined by
PERSIST_DATA_MAX_LENGTH (currently set to 256 bytes)
44. New Frameworks
Persistent Storage
To write data in persistent storage, call one of the persist_write functions:
You should check the return value for error codes (anything but 0 is bad news)
void handle_deinit() {
persist_write_bool(TRUTH_KEY, true);
persist_write_int(DOUGLAS_KEY, 42);
persist_write_string(USERNAME_KEY, “thomas”);
uint8_t byte_array[42];
persist_write_data(DATA_KEY, sizeof(byte_array), byte_array);
}
45. New Frameworks
Persistent Storage
The function persist_exists(key) returns a boolean indicating if the key
exists or not.
To read data from persistent storage, use the persist_read functions
void handle_init() {
bool truth = persist_read_bool(TRUTH_KEY);
int douglas_value = persist_read_int(DOUGLAS_KEY);
char username[20];
persist_read_string(USERNAME_KEY, 20, username);
uint8_t byte_array[42];
persist_read_data(DATA_KEY, sizeof(byte_array), byte_array);
}
47. New Frameworks
Persistent Storage
Store data on the watch
Persistent storage is perfect to save user settings, cache
data from the phone app, high scores, etc
Refer to Pebble Persistent Storage Guide
http://developer.getpebble.com/2/guides/persistent-storage.html
48. New Frameworks
PebbleKit JavaScript
Expand the reach of your Pebble apps with
JavaScript logic running on the phone
Make http calls on the phone, process the reply and send
it to your watchapp.
Send notification. Use the phone GPS.
Use a webview in the phone to provide a configuration
screen to your application.
49. New Frameworks
PebbleKit JavaScript
Add a pebble-js-app.js file in your project
Or use pebble new-project --javascript
When Pebble mobile application installs your pbw,
the JS is extracted and saved on the phone.
Your JavaScript code is started with your
watchapp/watchface and will run as long as your
app is in the foreground on Pebble.
50. New Frameworks
PebbleKit JavaScript
Pebble sandbox provides API to receive messages from the watch,
make http requests, send new messages to the watch, etc.
On the watch, AppMessage APIs are used to receive and send data.
PebbleKit JS is completely independent of the platform (iOS, Android).
51. New Frameworks
PebbleKit JavaScript
The sandbox provides a Pebble.addEventListener function to register
for events.
A ‘ready’ event is fired when your JavaScript is ready to execute.
PebbleEventListener.addEventListener("ready",
function(e) {
startRemoteRequest();
}
});
52. New Frameworks
PebbleKit JavaScript
Your JavaScript code can send notifications to the watch:
Pebble.showSimpleNotificationOnPebble(title, text)
You can also use the standard console.log() calls to log messages to
the Pebble console.
53. New Frameworks
PebbleKit JavaScript
Your JS code can also process messages coming from the watch
through the ‘appmessage’ event.
PebbleEventListener.addEventListener("appmessage",
function(e) {
var temperatureRequest = e.payload.temperatureRequest;
if (temperatureRequest) {
fetchWeather();
}
});
54. New Frameworks
PebbleKit JavaScript
To send messages to the watch, use Pebble.sendAppMessage()
PebbleKit JS automatically transforms JS dictionaries to Pebble’s
Dictionary
Pebble.sendAppMessage({ "icon": ICON_SUNNY, "temperature": "28oC"});
55. New Frameworks
PebbleKit JavaScript
The Pebble JavaScript sandbox provides the standard XMLHttpRequest
method to make http calls.
var req = new XMLHttpRequest();
req.open('GET', 'http://api.openweathermap.org/data/2.1/find/city?lat=37.830310&lon=-122.270831&cnt=1', true);
req.onload = function(e) {
if (req.readyState == 4 && req.status == 200) {
if(req.status == 200) {
var response = JSON.parse(req.responseText);
var temperature = result.list[0].main.temp;
var icon = result.list[0].main.icon;
Pebble.sendAppMessage({ "icon":icon, "temperature":temperature + "u00B0C"});
} else { console.log("Error"); }
}
}
req.send(null);
56. New Frameworks
PebbleKit JavaScript
Pebble sandbox provides several standard APIs:
• HTML5 Geolocation API through navigator.geolocation
• Local Storage APIs through window.localStorage
57. New Frameworks
PebbleKit JavaScript
Your application can show a Configure button on the phone screen
When the user clicks on this button, the configure event is fired
The html page can return information:
document.location.href = “pebblejs:///close#some-data-set”
Pebble.addEventListener("showConfiguration", function() {
console.log("showing configuration");
Pebble.openURL('http://assets.getpebble.com.s3-website-us-east-1.amazonaws.com/pebble-js/configurable.html');
});
Pebble.addEventListener("webviewclosed", function(e) {
console.log("configuration closed");
});
58. New Frameworks
PebbleKit JavaScript
Expand the reach of your watchapp with
JavaScript logic running on the phone
Make http calls on the phone, process the reply and send
it to your watchapp.
Send notification. Use the phone GPS.
Use a webview in the phone to provide a configuration
screen to your application.
Refer to Pebble JavaScript Guide
http://developer.getpebble.com/2/guides/javascript-guide.html