Loading...
Searching...
No Matches
Data In and Out

The AppMessage pipeline to the phone and the byte readers behind it. More...

Files

file  src/c/pebble/io/appmessage/appmessage.c
 AppMessage transport: weather requests out, settings + readings in. Decodes the wire format and hands results to the app through handlers, so it never reaches into the UI itself.
file  src/c/pebble/io/appmessage/appmessage.h
 AppMessage transport. Decodes the inbox and notifies the app through per-channel handlers, and queues the outbound weather, stock, and calendar requests through one outbox.
file  src/c/pebble/io/appmessage/appmessage_features.h
 Which of the phone's optional features a face has, worked out from the message keys it declares. The waf build defines a HAS_MESSAGE_KEY_* for every key in the face's messageKeys, and this turns those into one switch per feature, so every file asking the same question gets the same answer.
file  src/c/pebble/io/outbox_queue.h
 The outbox's work queue, its failed set, and the slot holding whatever is in flight.
file  src/c/pebble/io/tuple_read.c
 Reads a value out of an inbound message tuple.
file  src/c/pebble/io/tuple_read.h
 Reads a value out of an inbound message tuple.

Data Structures

struct  OutboxJob
 One job waiting to go out, or already in flight. More...
struct  OutboxQueue
 Everything the outbox is holding: what is waiting, what nacked, and what is out. More...
struct  [struct].s_handlers

Macros

#define APPMESSAGE_CUSTOM_COLORS_MAX   502
 Worst case combined custom-colours string. Two persist-key-sized halves plus the bar and the NUL.
#define OUTBOX_QUEUE_MAX   6
 Most jobs the work queue or the failed set holds at once.

Typedefs

typedef void(*) WeatherHandler(const WeatherMessage *msg)
 Called with one weather message, holding every group of readings it carried.
typedef void(*) CoordsHandler(const char *lat, const char *lon)
 Called with a fresh pair of coordinates.
typedef void(*) SettingsChangedHandler(bool time_or_date_changed)
 Called after a settings save that changed something.
typedef void(*) UnitChangedHandler(bool fahrenheit)
 Called when the wearer switches the temperature unit on the settings page.
typedef void(*) StockStripHandler(const uint8_t *buf, uint16_t len)
 Called with a packed watchlist strip. The handler owns the wire format.
typedef void(*) CalendarStripHandler(const uint8_t *buf, uint16_t len)
 Called with a packed agenda strip. The store owns the wire format.
typedef void(*) CustomColorsHandler(const char *combined)
 Called inbound with the combined custom-colours string, for the face to split and store.
typedef void(*) CustomColorsProvider(char *out, size_t n)
 Called outbound to rebuild the combined custom-colours string before a settings reply is sent.
typedef void(*) InboxCompleteHandler(void)
 Called once after every inbox message is fully handled.

Enumerations

enum  OutboxKind {
  OUTBOX_NONE , OUTBOX_WEATHER , OUTBOX_SETTINGS , OUTBOX_FRESH ,
  OUTBOX_STOCK , OUTBOX_CALENDAR
}
 What an outbox job sends. More...

Functions

void appmessage_on_weather (WeatherHandler cb)
 One weather message, every group it carried.
void appmessage_on_coords (CoordsHandler cb)
 Latitude and longitude.
void appmessage_on_settings_changed (SettingsChangedHandler cb)
 A setting changed on the phone.
void appmessage_on_unit_changed (UnitChangedHandler cb)
 The wearer switched the temperature unit.
void appmessage_on_stock_strip (StockStripHandler cb)
 Packed watchlist strip.
void appmessage_on_calendar_strip (CalendarStripHandler cb)
 Packed agenda strip.
void appmessage_on_custom_colors (CustomColorsHandler cb)
 Inbound: splits and stores the combined string.
void appmessage_set_custom_colors_provider (CustomColorsProvider cb)
 Outbound: rebuilds the combined string.
void appmessage_add_inbox_complete (InboxCompleteHandler cb)
 Adds work to run once after a whole inbound message is handled, after every channel in it.
void appmessage_open (uint32_t inbox_size)
 Register the SDK callbacks and open the inbox and outbox.
void appmessage_request_weather (void)
 Asks the phone for a fresh weather reading. The weather store calls this on its turn on the shared cadence. On a face that does not declare the weather keys it sends nothing and logs one warning the first time it is called. The weather keys are WEATHER_REQUEST, WEATHER_TEMPERATURE, WEATHER_CONDITIONS, and WEATHER_OK, and a face that declares only some of them fails to build, with each missing one named.
void appmessage_request_stock (void)
 Asks the phone for fresh quotes. The stock store calls this on its turn on the shared cadence. Does nothing on faces that do not declare the stock keys.
void appmessage_request_calendar (void)
 Asks the phone for a fresh agenda. The calendar store calls this on its turn on the shared cadence. Does nothing on faces that do not declare the calendar keys.
static bool outbox_busy (const OutboxQueue *outbox)
 Whether anything is in flight, which is what says the outbox is busy.
static bool outbox_pending (const OutboxQueue *outbox, OutboxKind kind)
 Whether this kind is already somewhere in the outbox.
static bool outbox_push (OutboxQueue *outbox, OutboxKind kind, int retries)
 Add a job to the work queue unless its kind is already pending.
static void outbox_pop_front (OutboxQueue *outbox)
 Drop the front job off the work queue, shifting the rest forward.
static void outbox_take_head (OutboxQueue *outbox)
 Take the head of the queue as the job now in flight.
static OutboxJob outbox_release (OutboxQueue *outbox)
 Mark whatever was in flight as settled, whichever way it went.
static void outbox_hold_failed (OutboxQueue *outbox, OutboxJob job)
 Hold a nacked job for the next pass, if it still has retries.
static int outbox_retry_pass (OutboxQueue *outbox)
 Move the whole failed set back into the work queue for another pass.
static void outbox_clear (OutboxQueue *outbox)
 Forget everything waiting, for a phone that is no longer there.
int32_t tuple_int_or (const Tuple *tuple, int32_t fallback)
 Reads an int tuple, whatever width the phone sent it at.
const char * tuple_str_or (const Tuple *tuple, const char *fallback)
 Reads a cstring tuple, or the fallback when it is not one that can be read.

Detailed Description

The AppMessage pipeline to the phone and the byte readers behind it.

The stores use the byte readers to unpack the packed strips the phone sends.

Typedef Documentation

◆ CalendarStripHandler

typedef void(*) CalendarStripHandler(const uint8_t *buf, uint16_t len)

Called with a packed agenda strip. The store owns the wire format.

Parameters
bufThe raw wire bytes.
lenHow many bytes there are.

◆ CoordsHandler

typedef void(*) CoordsHandler(const char *lat, const char *lon)

Called with a fresh pair of coordinates.

Parameters
latLatitude, pre-formatted as a dash string like "33-44".
lonLongitude, pre-formatted as a dash string like "-112-07".

◆ CustomColorsHandler

typedef void(*) CustomColorsHandler(const char *combined)

Called inbound with the combined custom-colours string, for the face to split and store.

Parameters
combinedThe combined string, such as "3 colours | flags".

◆ CustomColorsProvider

typedef void(*) CustomColorsProvider(char *out, size_t n)

Called outbound to rebuild the combined custom-colours string before a settings reply is sent.

Parameters
[out]outThe buffer to fill.
nThe size of out.

◆ InboxCompleteHandler

typedef void(*) InboxCompleteHandler(void)

Called once after every inbox message is fully handled.

Lets a store that took several channels in one push save them together in one write, rather than once per channel.

◆ SettingsChangedHandler

typedef void(*) SettingsChangedHandler(bool time_or_date_changed)

Called after a settings save that changed something.

Parameters
time_or_date_changedTrue when the date or time format changed, so the face should re-render the clock.

◆ StockStripHandler

typedef void(*) StockStripHandler(const uint8_t *buf, uint16_t len)

Called with a packed watchlist strip. The handler owns the wire format.

Parameters
bufThe raw wire bytes.
lenHow many bytes there are.

◆ UnitChangedHandler

typedef void(*) UnitChangedHandler(bool fahrenheit)

Called when the wearer switches the temperature unit on the settings page.

Not called for a restore, which brings the unit any reading already on the watch was fetched in.

Parameters
fahrenheitTrue when the new unit is Fahrenheit.

◆ WeatherHandler

typedef void(*) WeatherHandler(const WeatherMessage *msg)

Called with one weather message, holding every group of readings it carried.

The message is read straight off the inbox, so it only lives for this call. The pipeline does not know the unit label. The face adds "°C" or "°F" from its own setting when it draws.

Parameters
msgThe message. weather_reading_apply turns it into the kept reading.

Enumeration Type Documentation

◆ OutboxKind

enum OutboxKind

What an outbox job sends.

Enumerator
OUTBOX_NONE 

The zero value, so a default-initialized job slot reads as nothing rather than a real request.

OUTBOX_WEATHER 

A weather request.

OUTBOX_SETTINGS 

The settings reply.

OUTBOX_FRESH 

The short settings reply, only whether the watch booted with nothing saved.

OUTBOX_STOCK 

A stock request.

OUTBOX_CALENDAR 

A calendar request.

Function Documentation

◆ appmessage_add_inbox_complete()

void appmessage_add_inbox_complete ( InboxCompleteHandler cb)

Adds work to run once after a whole inbound message is handled, after every channel in it.

Unlike the channel handlers, this adds to a list rather than replacing a handler, so several stores can each commit what one message brought them. Adding the same function twice does nothing.

Parameters
cbThe work to run. NULL is ignored.

◆ appmessage_open()

void appmessage_open ( uint32_t inbox_size)

Register the SDK callbacks and open the inbox and outbox.

Call after settings_init and after the channel handlers are installed. The outbox is sized from the face's settings table, counting every string at its full buffer, so it needs nothing from the face.

The inbox is the face's to size, because the biggest message in is the settings page's save and Clay sends every message key in it, including ones the watch never reads. Add up the longest value each key on the settings page can hold plus 7 bytes of header per key, and leave some room over. A message bigger than the inbox is dropped whole and logged with its reason, so a settings save that never lands is the sign the number is too small.

Parameters
inbox_sizeThe inbox buffer in bytes. Anything over the platform maximum opens at the maximum.

◆ outbox_busy()

bool outbox_busy ( const OutboxQueue * outbox)
inlinestatic

Whether anything is in flight, which is what says the outbox is busy.

Parameters
outboxThe outbox to read.
Returns
True while a send is waiting on its sent or failed callback.

◆ outbox_clear()

void outbox_clear ( OutboxQueue * outbox)
inlinestatic

Forget everything waiting, for a phone that is no longer there.

Nothing reaches a phone that is not connected, so a store's next poll asks again once it is back rather than a stale queue draining into it.

Parameters
outboxThe outbox to empty.

◆ outbox_hold_failed()

void outbox_hold_failed ( OutboxQueue * outbox,
OutboxJob job )
inlinestatic

Hold a nacked job for the next pass, if it still has retries.

Parameters
outboxThe outbox to hold it in.
jobThe job that just nacked.

◆ outbox_pending()

bool outbox_pending ( const OutboxQueue * outbox,
OutboxKind kind )
inlinestatic

Whether this kind is already somewhere in the outbox.

Covers all three places a job can be, so a poll that repeats while an earlier one is still working its way out does not queue a second copy of the same request.

Parameters
outboxThe outbox to read.
kindThe job kind to look for.
Returns
True when that kind is in flight, queued, or held after a nack.

◆ outbox_pop_front()

void outbox_pop_front ( OutboxQueue * outbox)
inlinestatic

Drop the front job off the work queue, shifting the rest forward.

Parameters
outboxThe outbox to drop from.

◆ outbox_push()

bool outbox_push ( OutboxQueue * outbox,
OutboxKind kind,
int retries )
inlinestatic

Add a job to the work queue unless its kind is already pending.

Parameters
outboxThe outbox to add to.
kindThe job kind to send.
retriesRetry passes left if the first send nacks.
Returns
True when the job was added, false when it was already pending or the queue is full.

◆ outbox_release()

OutboxJob outbox_release ( OutboxQueue * outbox)
inlinestatic

Mark whatever was in flight as settled, whichever way it went.

Parameters
outboxThe outbox to clear.
Returns
The job that was in flight, so a nacked one can be handed to outbox_hold_failed.

◆ outbox_retry_pass()

int outbox_retry_pass ( OutboxQueue * outbox)
inlinestatic

Move the whole failed set back into the work queue for another pass.

Parameters
outboxThe outbox to move within.
Returns
How many jobs were moved back.

◆ outbox_take_head()

void outbox_take_head ( OutboxQueue * outbox)
inlinestatic

Take the head of the queue as the job now in flight.

The caller sends it first and only takes it once the send was accepted, so a refused send leaves the head where it was.

Parameters
outboxThe outbox to take from.

◆ tuple_int_or()

int32_t tuple_int_or ( const Tuple * tuple,
int32_t fallback )

Reads an int tuple, whatever width the phone sent it at.

A sender may pick TUPLE_INT or TUPLE_UINT for an integer, so both are accepted and the choice only decides what the top bit means.

Parameters
tupleThe tuple, or NULL when the key was absent.
fallbackReturned when the tuple is absent, is not an int, or carries a width no sender may use.
Returns
The value, or fallback.

◆ tuple_str_or()

const char * tuple_str_or ( const Tuple * tuple,
const char * fallback )

Reads a cstring tuple, or the fallback when it is not one that can be read.

Parameters
tupleThe tuple, or NULL when the key was absent.
fallbackReturned when the tuple is absent, is not a cstring, or carries no terminator inside its own length.
Returns
The string, or fallback.