Loading...
Searching...
No Matches
appmessage.c File Reference

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. More...

#include "io/appmessage/appmessage.h"
#include "io/appmessage/appmessage_features.h"
#include "io/callback_list.h"
#include "io/outbox_queue.h"
#include "io/tuple_read.h"
#include "math/scale.h"
#include "system/settings/settings.h"
#include "wire/wire_caps.g.h"
#include <limits.h>

Data Structures

struct  [struct].s_handlers

Macros

#define INBOX_COMPLETE_MAX   4
 Room for the work that waits for a whole inbound message, one entry per store that wants it.
Outbox queue limits

Only one AppMessage send can be in flight at a time, so every outbound message (the weather, stock and calendar requests plus the settings reply) goes through one queue. It sends the head, waits for its sent or failed callback, then sends the next, and drains a pass at a time.

A job the phone nacks is held in a failed set and retried on a later pass. Its pkjs was usually asleep or busy, and that first send is often what wakes it. Holding it back means a whole poll is not lost to one nack and left stale until the next interval, and neither is a settings reply.

#define REQUEST_RETRY_MAX   3
 Retry passes a nacked job gets before it is dropped.
#define REQUEST_RETRY_DELAY_MS   5000
 Delay before the next retry pass, in ms.

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.
static void pump (void)
 Send the head job when the outbox is free, once the phone is there.
static uint32_t settings_reply_size (void)
 The most outbox bytes the settings reply could take, counting everything write_settings writes. The outbox is opened at this, so no settings change can outgrow it later.
static bool write_settings (DictionaryIterator *iter)
 Write the settings reply payload into the outbox iterator.
static bool kind_has_key (OutboxKind kind)
 Whether this face declares the key a kind is sent under.
static bool send_job (OutboxKind kind)
 Build the message for kind and hand it to the outbox.
static void enqueue (OutboxKind kind, int retries)
 Add a job to the work queue unless its kind is already pending, then pump either way.
static void retry_pass (void *data)
 Move the whole failed set back into the work queue for another pass, then pump.
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 void send_settings (void)
 Queue the settings reply so it serializes with the data requests through the one outbox.
static void inbox_received_callback (DictionaryIterator *iterator, void *context)
 Apply an inbox message: weather, coords, and any changed settings.
static void inbox_dropped_callback (AppMessageResult reason, void *context)
 Log a dropped inbox message.
static void outbox_failed_callback (DictionaryIterator *iter, AppMessageResult reason, void *context)
 Outbox send was nacked (usually the phone's pkjs is asleep).
static void outbox_sent_callback (DictionaryIterator *iter, void *context)
 Outbox delivered. Frees the outbox and sends the next queued job.
void appmessage_open (uint32_t inbox_size)
 Register the SDK callbacks and open the inbox and outbox.

Variables

static struct  s_handlers
 The registered channel handlers. Each one stays NULL until a consumer opts in.
static CallbackListFn s_inbox_complete_entries [INBOX_COMPLETE_MAX]
 That work, in the order it was added.
static CallbackList s_inbox_complete = {s_inbox_complete_entries, INBOX_COMPLETE_MAX, 0}
 The list over that storage.
static OutboxQueue s_outbox
 What is queued, what nacked, and what is in flight.
static AppTimer * s_retry_timer
 Delay before the next retry pass.
static uint32_t s_outbox_size
 The outbox buffer size appmessage_open asked for.

Detailed Description

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.

Function Documentation

◆ enqueue()

void enqueue ( OutboxKind kind,
int retries )
static

Add a job to the work queue unless its kind is already pending, then pump either way.

Parameters
kindThe job kind to send.
retriesRetry passes left if the first send nacks.

◆ inbox_dropped_callback()

void inbox_dropped_callback ( AppMessageResult reason,
void * context )
static

Log a dropped inbox message.

Parameters
reasonThe reason the message was dropped.
contextApplication context (unused).

◆ inbox_received_callback()

void inbox_received_callback ( DictionaryIterator * iterator,
void * context )
static

Apply an inbox message: weather, coords, and any changed settings.

Parameters
iteratorThe dictionary iterator containing the message.
contextApplication context (unused).

◆ kind_has_key()

bool kind_has_key ( OutboxKind kind)
static

Whether this face declares the key a kind is sent under.

Parameters
kindThe job kind to check.
Returns
True when send_job has something to write for kind.

◆ outbox_failed_callback()

void outbox_failed_callback ( DictionaryIterator * iter,
AppMessageResult reason,
void * context )
static

Outbox send was nacked (usually the phone's pkjs is asleep).

Frees the outbox and holds the job for a later retry pass while it has retries left, then pumps the rest of the queue.

Parameters
iterThe dictionary iterator.
reasonThe reason the message failed.
contextApplication context (unused).

◆ outbox_sent_callback()

void outbox_sent_callback ( DictionaryIterator * iter,
void * context )
static

Outbox delivered. Frees the outbox and sends the next queued job.

Parameters
iterThe dictionary iterator.
contextApplication context (unused).

◆ retry_pass()

void retry_pass ( void * data)
static

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

Parameters
dataThe timer context (unused).

◆ send_job()

bool send_job ( OutboxKind kind)
static

Build the message for kind and hand it to the outbox.

Parameters
kindThe job kind to send.
Returns
False if the outbox refused it or a face does not declare the key for kind.

◆ settings_reply_size()

uint32_t settings_reply_size ( void )
static

The most outbox bytes the settings reply could take, counting everything write_settings writes. The outbox is opened at this, so no settings change can outgrow it later.

Returns
The whole message's size, the dictionary's own header included.

◆ write_settings()

bool write_settings ( DictionaryIterator * iter)
static

Write the settings reply payload into the outbox iterator.

The watch persist is the source of truth so Clay can seed its store from it. Carries the request key as a marker, the current settings, a fresh flag, and the custom colours. settings_reply_size counts the same four things.

Parameters
iterThe outbox iterator to write into.
Returns
True when all of it was written, false when the outbox ran out of room partway.