Pebble Foundation Classes  0.2.0
C++ for Pebble
AppMessage

Bi-directional communication between phone apps and Pebble watchapps. More...

Collaboration diagram for AppMessage:

Macros

#define APP_MESSAGE_INBOX_SIZE_MINIMUM   124
 
#define APP_MESSAGE_OUTBOX_SIZE_MINIMUM   636
 

Typedefs

typedef void(* AppMessageInboxReceived) (DictionaryIterator *iterator, void *context)
 
typedef void(* AppMessageInboxDropped) (AppMessageResult reason, void *context)
 
typedef void(* AppMessageOutboxSent) (DictionaryIterator *iterator, void *context)
 
typedef void(* AppMessageOutboxFailed) (DictionaryIterator *iterator, AppMessageResult reason, void *context)
 

Enumerations

enum  AppMessageResult {
  APP_MSG_OK = 0, APP_MSG_SEND_TIMEOUT = 1 << 1, APP_MSG_SEND_REJECTED = 1 << 2, APP_MSG_NOT_CONNECTED = 1 << 3,
  APP_MSG_APP_NOT_RUNNING = 1 << 4, APP_MSG_INVALID_ARGS = 1 << 5, APP_MSG_BUSY = 1 << 6, APP_MSG_BUFFER_OVERFLOW = 1 << 7,
  APP_MSG_ALREADY_RELEASED = 1 << 9, APP_MSG_CALLBACK_ALREADY_REGISTERED = 1 << 10, APP_MSG_CALLBACK_NOT_REGISTERED = 1 << 11, APP_MSG_OUT_OF_MEMORY = 1 << 12,
  APP_MSG_CLOSED = 1 << 13, APP_MSG_INTERNAL_ERROR = 1 << 14, APP_MSG_INVALID_STATE = 1 << 15
}
 AppMessage result codes. More...
 

Functions

AppMessageResult app_message_open (const uint32_t size_inbound, const uint32_t size_outbound)
 
void app_message_deregister_callbacks (void)
 
void * app_message_get_context (void)
 
void * app_message_set_context (void *context)
 
AppMessageInboxReceived app_message_register_inbox_received (AppMessageInboxReceived received_callback)
 
AppMessageInboxDropped app_message_register_inbox_dropped (AppMessageInboxDropped dropped_callback)
 
AppMessageOutboxSent app_message_register_outbox_sent (AppMessageOutboxSent sent_callback)
 
AppMessageOutboxFailed app_message_register_outbox_failed (AppMessageOutboxFailed failed_callback)
 
uint32_t app_message_inbox_size_maximum (void)
 
uint32_t app_message_outbox_size_maximum (void)
 
AppMessageResult app_message_outbox_begin (DictionaryIterator **iterator)
 
AppMessageResult app_message_outbox_send (void)
 

Detailed Description

Bi-directional communication between phone apps and Pebble watchapps.

AppMessage is a bi-directional messaging subsystem that enables communication between phone apps and Pebble watchapps. This is accomplished by allowing phone and watchapps to exchange arbitrary sets of key/value pairs. The key/value pairs are stored in the form of a Dictionary, the layout of which is left for the application developer to define.

AppMessage implements a push-oriented messaging protocol, enabling your app to call functions and methods to push messages from Pebble to phone and vice versa. The protocol is symmetric: both Pebble and the phone can send messages. All messages are acknowledged. In this context, there is no client-server model, as such.

During the sending phase, one side initiates the communication by transferring a dictionary over the air. The other side then receives this message and is given an opportunity to perform actions on that data. As soon as possible, the other side is expected to reply to the message with a simple acknowledgment that the message was received successfully.

PebbleKit JavaScript provides you with a set of standard JavaScript APIs that let your app receive messages from the watch, make HTTP requests, and send new messages to the watch. AppMessage APIs are used to send and receive data. A Pebble watchapp can use the resources of the connected phone to fetch information from web services, send information to web APIs, or store login credentials. On the JavaScript side, you communicate with Pebble via a Pebble object exposed in the namespace.

Messages always need to get either ACKnowledged or "NACK'ed," that is, not acknowledged. If not, messages will result in a time-out failure. The AppMessage subsystem takes care of this implicitly. In the phone libraries, this step is a bit more explicit.

The Pebble watch interfaces make a distinction between the Inbox and the Outbox calls. The Inbox receives messages from the phone on the watch; the Outbox sends messages from the watch to the phone. These two buffers can be managed separately.

Warning

A critical constraint of AppMessage is that messages are limited in size. An ingoing (outgoing) message larger than the inbox (outbox) will not be transmitted and will generate an error. You can choose your inbox and outbox size when you call app_message_open().

Pebble SDK provides a static minimum guaranteed size (APP_MESSAGE_INBOX_SIZE_MINIMUM and APP_MESSAGE_OUTBOX_SIZE_MINIMUM). Requesting a buffer of the minimum guaranteed size (or smaller) is always guaranteed to succeed on all Pebbles in this SDK version or higher, and with every phone.

In some context, Pebble might be able to provide your application with larger inbox/outbox. You can call app_message_inbox_size_maximum() and app_message_outbox_size_maximum() in your code to get the largest possible value you can use.

To always get the largest buffer available, follow this best practice:

app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum())

AppMessage uses your application heap space. That means that the sizes you pick for the AppMessage inbox and outbox buffers are important in optimizing your app’s performance. The more you use for AppMessage, the less space you’ll have for the rest of your app.

To register callbacks, you should call app_message_register_inbox_received(), app_message_register_inbox_dropped(), app_message_register_outbox_sent(), app_message_register_outbox_failed().

Pebble recommends that you call them before app_message_open() to ensure you do not miss a message arriving between starting AppMessage and registering the callback. You can set a context that will be passed to all the callbacks with app_message_set_context().

In circumstances that may not be ideal, when using AppMessage several types of errors may occur. For example:

Other errors are possible and described by AppMessageResult. A client of the AppMessage interface should use the result codes to be more robust in the face of communication problems either in the field or while debugging.

Refer to the for a conceptual overview and code usage.

For code examples, refer to the SDK Examples that directly use App Message. These include:

Macro Definition Documentation

◆ APP_MESSAGE_INBOX_SIZE_MINIMUM

#define APP_MESSAGE_INBOX_SIZE_MINIMUM   124

As long as the firmware maintains its current major version, inboxes of this size or smaller will be allowed.

See also
app_message_inbox_size_maximum()
APP_MESSAGE_OUTBOX_SIZE_MINIMUM

◆ APP_MESSAGE_OUTBOX_SIZE_MINIMUM

#define APP_MESSAGE_OUTBOX_SIZE_MINIMUM   636

As long as the firmware maintains its current major version, outboxes of this size or smaller will be allowed.

See also
app_message_outbox_size_maximum()
APP_MESSAGE_INBOX_SIZE_MINIMUM

Typedef Documentation

◆ AppMessageInboxDropped

typedef void(* AppMessageInboxDropped) (AppMessageResult reason, void *context)

Called after an incoming message is dropped.

Parameters
[in]resultThe reason why the message was dropped. Some possibilities include APP_MSG_BUSY and APP_MSG_BUFFER_OVERFLOW.
[in]contextPointer to application data as specified when registering the callback.

Note that you can call app_message_outbox_begin() from this handler to prepare a new message. This will invalidate the previous dictionary iterator; do not use it after calling app_message_outbox_begin().

◆ AppMessageInboxReceived

typedef void(* AppMessageInboxReceived) (DictionaryIterator *iterator, void *context)

Called after an incoming message is received.

Parameters
[in]iteratorThe dictionary iterator to the received message. Never NULL. Note that the iterator cannot be modified or saved off. The library may need to re-use the buffered space where this message is supplied. Returning from the callback indicates to the library that the received message contents are no longer needed or have already been externalized outside its buffering space and iterator.
[in]contextPointer to application data as specified when registering the callback.

◆ AppMessageOutboxFailed

typedef void(* AppMessageOutboxFailed) (DictionaryIterator *iterator, AppMessageResult reason, void *context)

Called after an outbound message has not been sent successfully.

Parameters
[in]iteratorThe dictionary iterator to the sent message. The iterator will be in the final state that was sent. Note that the iterator cannot be modified or saved off as the library will re-open the dictionary with dict_begin() after this callback returns.
[in]resultThe result of the operation. Some possibilities for the value include APP_MSG_SEND_TIMEOUT, APP_MSG_SEND_REJECTED, APP_MSG_NOT_CONNECTED, APP_MSG_APP_NOT_RUNNING, and the combination (APP_MSG_NOT_CONNECTED | APP_MSG_APP_NOT_RUNNING).
contextPointer to application data as specified when registering the callback.

Note that you can call app_message_outbox_begin() from this handler to prepare a new message. This will invalidate the previous dictionary iterator; do not use it after calling app_message_outbox_begin().

◆ AppMessageOutboxSent

typedef void(* AppMessageOutboxSent) (DictionaryIterator *iterator, void *context)

Called after an outbound message has been sent and the reply has been received.

Parameters
[in]iteratorThe dictionary iterator to the sent message. The iterator will be in the final state that was sent. Note that the iterator cannot be modified or saved off as the library will re-open the dictionary with dict_begin() after this callback returns.
[in]contextPointer to application data as specified when registering the callback.

Enumeration Type Documentation

◆ AppMessageResult

AppMessage result codes.

Enumerator
APP_MSG_OK 

(0) All good, operation was successful.

APP_MSG_SEND_TIMEOUT 

(2) The other end did not confirm receiving the sent data with an (n)ack in time.

APP_MSG_SEND_REJECTED 

(4) The other end rejected the sent data, with a "nack" reply.

APP_MSG_NOT_CONNECTED 

(8) The other end was not connected.

APP_MSG_APP_NOT_RUNNING 

(16) The local application was not running.

APP_MSG_INVALID_ARGS 

(32) The function was called with invalid arguments.

APP_MSG_BUSY 

(64) There are pending (in or outbound) messages that need to be processed first before new ones can be received or sent.

APP_MSG_BUFFER_OVERFLOW 

(128) The buffer was too small to contain the incoming message.

APP_MSG_ALREADY_RELEASED 

(512) The resource had already been released.

APP_MSG_CALLBACK_ALREADY_REGISTERED 

(1024) The callback was already registered.

APP_MSG_CALLBACK_NOT_REGISTERED 

(2048) The callback could not be deregistered, because it had not been registered before.

APP_MSG_OUT_OF_MEMORY 

(4096) The system did not have sufficient application memory to perform the requested operation.

APP_MSG_CLOSED 

(8192) App message was closed.

APP_MSG_INTERNAL_ERROR 

(16384) An internal OS error prevented AppMessage from completing an operation.

APP_MSG_INVALID_STATE 

(32768) The function was called while App Message was not in the appropriate state.

Function Documentation

◆ app_message_deregister_callbacks()

void app_message_deregister_callbacks ( void  )

Deregisters all callbacks and their context.

◆ app_message_get_context()

void* app_message_get_context ( void  )

Gets the context that will be passed to all AppMessage callbacks.

Returns
The current context on record.

◆ app_message_inbox_size_maximum()

uint32_t app_message_inbox_size_maximum ( void  )

Programatically determine the inbox size maximum in the current configuration.

Returns
The inbox size maximum on this firmware.
See also
APP_MESSAGE_INBOX_SIZE_MINIMUM
app_message_outbox_size_maximum()

◆ app_message_open()

AppMessageResult app_message_open ( const uint32_t  size_inbound,
const uint32_t  size_outbound 
)

Open AppMessage to transfers.

Use dict_calc_buffer_size_from_tuplets() or dict_calc_buffer_size() to estimate the size you need.

Parameters
[in]size_inboundThe required size for the Inbox buffer
[in]size_outboundThe required size for the Outbox buffer
Returns
A result code such as APP_MSG_OK or APP_MSG_OUT_OF_MEMORY.
Note
It is recommended that if the Inbox will be used, that at least the Inbox callbacks should be registered before this call. Otherwise it is possible for an Inbox message to be NACK'ed without being seen by the application.

◆ app_message_outbox_begin()

AppMessageResult app_message_outbox_begin ( DictionaryIterator **  iterator)

Begin writing to the Outbox's Dictionary buffer.

Parameters
[out]iteratorLocation to write the DictionaryIterator pointer. This will be NULL on failure.
Returns
A result code, including but not limited to APP_MSG_OK, APP_MSG_INVALID_ARGS or APP_MSG_BUSY.
Note
After a successful call, one can add values to the dictionary using functions like dict_write_data() and friends.
See also
Dictionary

◆ app_message_outbox_send()

AppMessageResult app_message_outbox_send ( void  )

Sends the outbound dictionary.

Returns
A result code, including but not limited to APP_MSG_OK or APP_MSG_BUSY. The APP_MSG_OK code does not mean that the message was sent successfully, but only that the start of processing was successful. Since this call is asynchronous, callbacks provide the final result instead.
See also
AppMessageOutboxSent
AppMessageOutboxFailed

◆ app_message_outbox_size_maximum()

uint32_t app_message_outbox_size_maximum ( void  )

Programatically determine the outbox size maximum in the current configuration.

Returns
The outbox size maximum on this firmware.
See also
APP_MESSAGE_OUTBOX_SIZE_MINIMUM
app_message_inbox_size_maximum()

◆ app_message_register_inbox_dropped()

AppMessageInboxDropped app_message_register_inbox_dropped ( AppMessageInboxDropped  dropped_callback)

Registers a function that will be called after any Inbox message is received but dropped by the system.

Only one callback may be registered at a time. Each subsequent call to this function will replace the previous callback. The callback is optional; setting it to NULL will deregister the current callback and no function will be called anymore.

Parameters
[in]dropped_callbackThe callback that will be called going forward; NULL to not have a callback.
Returns
The previous callback (or NULL) that was on record.

◆ app_message_register_inbox_received()

AppMessageInboxReceived app_message_register_inbox_received ( AppMessageInboxReceived  received_callback)

Registers a function that will be called after any Inbox message is received successfully.

Only one callback may be registered at a time. Each subsequent call to this function will replace the previous callback. The callback is optional; setting it to NULL will deregister the current callback and no function will be called anymore.

Parameters
[in]received_callbackThe callback that will be called going forward; NULL to not have a callback.
Returns
The previous callback (or NULL) that was on record.

◆ app_message_register_outbox_failed()

AppMessageOutboxFailed app_message_register_outbox_failed ( AppMessageOutboxFailed  failed_callback)

Registers a function that will be called after any Outbox message is not sent with a timely ACK reply. The call to app_message_outbox_send() must have succeeded.

Only one callback may be registered at a time. Each subsequent call to this function will replace the previous callback. The callback is optional; setting it to NULL will deregister the current callback and no function will be called anymore.

Parameters
[in]failed_callbackThe callback that will be called going forward; NULL to not have a callback.
Returns
The previous callback (or NULL) that was on record.

◆ app_message_register_outbox_sent()

AppMessageOutboxSent app_message_register_outbox_sent ( AppMessageOutboxSent  sent_callback)

Registers a function that will be called after any Outbox message is sent and an ACK reply occurs in a timely fashion.

Only one callback may be registered at a time. Each subsequent call to this function will replace the previous callback. The callback is optional; setting it to NULL will deregister the current callback and no function will be called anymore.

Parameters
[in]sent_callbackThe callback that will be called going forward; NULL to not have a callback.
Returns
The previous callback (or NULL) that was on record.

◆ app_message_set_context()

void* app_message_set_context ( void *  context)

Sets the context that will be passed to all AppMessage callbacks.

Parameters
[in]contextThe context that will be passed to all AppMessage callbacks.
Returns
The previous context that was on record.