Weather, health, calendar, stocks, and the other readings a face shows. More...
Files | |
| file | src/c/pebble/io/stores/calendar_store.c |
| The active calendar store: holds the agenda, owns the appmessage calendar channel, and asks the phone for more whenever its turn on the face's cadence finds a poll due. | |
| file | src/c/pebble/io/stores/calendar_store.h |
| Active calendar store. It owns the appmessage calendar channel and its place on the shared cadence, so a face just hands it the rules (live / poll interval), optionally seeds it, then reads the events and subscribes for repaints. The phone data flows straight in and nobody wires it. | |
| file | src/c/pebble/io/stores/health_store.c |
| The active health store: reads the watch's health service and holds the numbers. It owns the service accessors too so it is the single point of truth for health. | |
| file | src/c/pebble/io/stores/health_store.h |
| Active health store. It subscribes to the watch's health service itself and holds the readings, so a face just hands it the rules, optionally seeds it, then reads the numbers back. | |
| file | src/c/pebble/io/stores/location_store.c |
| The active location store: holds the phone's coordinates and owns the appmessage coords channel. | |
| file | src/c/pebble/io/stores/location_store.h |
| Active location store. It owns the appmessage coords channel (the same phone geolocation the weather rides on), so a face hands it the rules, optionally seeds it, then reads lat/lon back. There's no poll timer. Coords arrive alongside weather. | |
| file | src/c/pebble/io/stores/stock_store.c |
| The active stock store: holds the quotes, owns the appmessage stock channel, and asks the phone for more whenever its turn on the face's cadence finds a poll due. | |
| file | src/c/pebble/io/stores/stock_store.h |
| Active stock store. It owns the appmessage stock channel and its place on the shared cadence, so a face just hands it the rules (live / poll interval), optionally seeds it, then reads the slots and subscribes for repaints. The phone data flows straight in and nobody wires it. | |
| file | src/c/pebble/io/stores/store_cadence.c |
| Holds the list of work the stores want run on the face's cadence. | |
| file | src/c/pebble/io/stores/store_cadence.h |
| The shared cadence the stores hang their periodic work on. | |
| file | src/c/pebble/io/stores/store_fetch.c |
| The fetch timing the polling stores share, in one copy every store links against. | |
| file | src/c/pebble/io/stores/store_fetch.h |
| The fetch timing the polling stores share: the one-shot catch-up, the cadence turn, and what an init or a reconfigure does to them. | |
| file | src/c/pebble/io/stores/store_persist.c |
| The save that skips an unchanged reading and the restore that feeds it, in one copy every store links against. | |
| file | src/c/pebble/io/stores/store_persist.h |
| Shared persist save and restore helpers for the stores. | |
| file | src/c/pebble/io/stores/store_poll.c |
| The polling decisions the weather, stock, and calendar stores share. | |
| file | src/c/pebble/io/stores/store_poll.h |
| Wall-clock deadlines for the stores that poll the phone. | |
| file | src/c/pebble/io/stores/store_sum.c |
| The checksum the stores compare before saving, in one copy every store links against. | |
| file | src/c/pebble/io/stores/store_sum.h |
| A checksum of a store's reading, so a reply that brings nothing new costs no flash write. | |
| file | src/c/pebble/io/stores/system_store.c |
| The active system store: holds the battery + bluetooth state and subscribes to the battery and connection services itself. The alarm is read through on demand. | |
| file | src/c/pebble/io/stores/system_store.h |
| Active system store: the watch's own battery, bluetooth and next-alarm state. It subscribes to the battery and connection services itself and buzzes on a bluetooth change through a policy the face installs (so the store never has to know about settings or buzzing). | |
| file | src/c/pebble/io/stores/time_store.c |
| The active time store: holds the current time and owns the tickers that update it. | |
| file | src/c/pebble/io/stores/time_store.h |
| Active time store. It owns the tickers (the minute tick, the swatch .beats AppTimer, and the hour tick) and swaps between them for the current cadence, so a face just hands it the rules and reads the time back. | |
| file | src/c/pebble/io/stores/weather_store.c |
| The active weather store: holds the readings, owns the appmessage weather channels, and asks the phone for more whenever its turn on the face's cadence finds a poll due. | |
| file | src/c/pebble/io/stores/weather_store.h |
| Active weather store. It owns the appmessage weather channels and its place on the shared cadence, so a face just hands it the rules (live / poll interval), optionally seeds it, then reads the values and subscribes for repaints. The phone data flows straight in and nobody wires it. | |
Data Structures | |
| struct | CalendarConfig |
| The rules a face hands the store, built from its own settings so the store names no SETTING_*. More... | |
| struct | CalendarSeed |
| Optional prefill: shown until the first real reading lands, or pinned when live = false. More... | |
| struct | HealthConfig |
| The rules a face hands the store. More... | |
| struct | HealthSeed |
| Optional prefill, or pinned readings when live = false. More... | |
| struct | LocationConfig |
| The rules a face hands the store. More... | |
| struct | LocationSeed |
| Optional prefill, or pinned coords when live = false. On a live store a seed takes the place of restoring the last real fix, and shows until the phone sends coordinates. A seed is never saved, so the fix on flash stays as it was for the next launch without one. More... | |
| struct | StockConfig |
| The rules a face hands the store, built from its own settings so the store names no SETTING_*. More... | |
| struct | StockSeed |
| Optional prefill: shown until the first real reading lands, or pinned when live = false. More... | |
| struct | StoreFetch |
| One store's polling state, its catch-up timer, and how it asks the phone. More... | |
| struct | StorePoll |
| One store's polling: its interval, whether it polls at all, and when it is next due. More... | |
| struct | SystemConfig |
| The rules a face hands the store. More... | |
| struct | SystemSeed |
| Optional prefill, or pinned state when live = false. More... | |
| struct | TimeConfig |
| The rules a face hands the store, built from its own settings so the store names no SETTING_*. More... | |
| struct | WeatherConfig |
| The rules a face hands the store, built from its own settings so the store names no SETTING_*. More... | |
| struct | WeatherSeed |
| Optional prefill: shown until the first real reading lands, or pinned when live = false. More... | |
| struct | [struct].s_state |
Macros | |
| #define | STORE_CADENCE_MAX 8 |
| Room for one entry per store that wants the cadence. | |
| #define | STORE_READING_SIZE(state, stamp) |
| How many leading bytes of a store's blob are the reading, which is everything before its sync time. | |
| #define | WEATHER_SEED_EMPTY |
Typedefs | |
| typedef void(*) | BtVibePolicy(bool connected) |
| Called on a real bluetooth transition (a change, not the first reading), so the face can buzz however its own settings say. NULL for a silent link change. | |
Functions | |
| void | calendar_store_init (CalendarConfig cfg, const CalendarSeed *seed) |
| Start the store with its rules. Pass seed = NULL for normal use. | |
| void | calendar_store_reconfigure (CalendarConfig cfg) |
| Re-apply the rules (e.g. the poll interval changed). Moves the next poll to the new interval, and switching the store off here stops it asking the phone. | |
| void | calendar_store_subscribe (void(*cb)(void)) |
| Hand it the function to call when the agenda changes (the screen redraw). | |
| const CalendarStrip * | calendar_store_strip (void) |
| The whole agenda strip. count is 0 until a reading lands. | |
| const CalendarEvent * | calendar_store_event (uint8_t index) |
| One event by index, or NULL when the index is past what is filled. | |
| int | calendar_store_age_s (void) |
| How many seconds since the last reading turned up, or -1 if we have none. | |
| void | health_store_init (HealthConfig cfg, const HealthSeed *seed) |
| Start the store with its rules. Pass seed = NULL for normal use. | |
| void | health_store_subscribe (void(*cb)(void)) |
| Hand it the function to call when the numbers change (the screen redraw). | |
| uint8_t * | health_store_hr_history (void) |
| The last hour of heart rate readings, one per minute (a 60 slot buffer). The store fills it on each update. The little charts read it back out. | |
| const uint16_t * | health_store_step_hourly (void) |
| Today's steps split into per-hour buckets, one slot per hour from midnight (24 slots). The bar chart reads it back out. | |
| int | health_store_step_hours (void) |
| How many of the hourly step buckets hold a real value (0 to 24). Steps count 0 as a real reading (a quiet hour), so a chart needs the count rather than a no-data marker. | |
| int | health_store_hr (void) |
| The heart rate in beats per minute, or -1 if we have not got one yet. | |
| int | health_store_steps (void) |
| The steps taken so far today, or -1 if we have not got one yet. | |
| int | health_store_calories (void) |
| The active calories so far today, or -1 if we have not got one yet. | |
| int | health_store_sleep_min (void) |
| The minutes of sleep, or -1 if we have not got one yet. | |
| int | health_store_active_min (void) |
| The active minutes so far today, or -1 if we have not got one yet. | |
| int | health_store_distance_m (void) |
| Today's walked distance in meters, or 0 if we cannot read it. | |
| void | location_store_init (LocationConfig cfg, const LocationSeed *seed) |
| Start the store with its rules. Pass seed = NULL for normal use. | |
| void | location_store_subscribe (void(*cb)(void)) |
| Hand it the function to call when the coordinates change (the screen redraw). | |
| const char * | location_store_lat (void) |
| The latitude string, or empty if we have not got one yet. | |
| const char * | location_store_lon (void) |
| The longitude string, or empty if we have not got one yet. | |
| void | stock_store_init (StockConfig cfg, const StockSeed *seed) |
| Start the store with its rules. Pass seed = NULL for normal use. | |
| void | stock_store_reconfigure (StockConfig cfg) |
| Re-apply the rules (e.g. the poll interval changed). Moves the next poll to the new interval, and switching the store off here stops it asking the phone. | |
| void | stock_store_subscribe (void(*cb)(void)) |
| Hand it the function to call when a quote changes (the screen redraw). | |
| const StockStrip * | stock_store_strip (void) |
| The whole watchlist strip. count is 0 until a reading lands. | |
| const StockSlot * | stock_store_slot (uint8_t index) |
| One slot by index, or NULL when the index is past what is filled. | |
| int | stock_store_age_s (void) |
| How many seconds since the last reading turned up, or -1 if we have none. | |
| void | store_cadence_register (void(*cb)(void)) |
Ask for cb to run each time the face's cadence comes round. A store calls this from its own init, so no face has to wire it up by hand. | |
| void | store_cadence_fire (void) |
| Run everything registered, in the order it was registered. The time store calls this from its ticker, before it tells the face the time moved. | |
| void | store_fetch_fire (void *data) |
| The one-shot fetch's timer callback. Clears the timer and asks the phone. | |
| void | store_fetch_stop (StoreFetch *fetch) |
| Cancel the one-shot fetch, if one is armed. | |
| void | store_fetch_arm (StoreFetch *fetch) |
| Arm the one-shot fetch after first_ms, unless one is already waiting. | |
| void | store_fetch_turn (StoreFetch *fetch, time_t now) |
| The store's turn on the face's cadence. Asks the phone when the deadline has come round. | |
| void | store_fetch_start (StoreFetch *fetch, int poll_min, bool live, time_t now) |
| What a store's init does with its polling. Takes the interval, then arms one fetch shortly after launch when polling is on, so the store is not blank while the first deadline is coming. | |
| void | store_fetch_reconfigure (StoreFetch *fetch, int poll_min, bool live, time_t now, bool empty) |
| What a store's reconfigure does with its polling. | |
| static bool | store_restore (uint32_t key, void *state, size_t size, uint8_t tag) |
Restore a saved blob into state, but only when it is this store's own current layout. | |
| static bool | store_save (uint32_t key, void *state, size_t size, uint8_t tag) |
| Save a store's blob with its tag stamped in, so the next restore can recognize it. | |
| bool | store_save_changed (uint32_t key, void *state, size_t size, size_t reading_size, uint8_t tag, uint32_t *saved_sum) |
| Save a store's blob only when its reading is different from what is already on flash. | |
| bool | store_restore_reading (uint32_t key, void *state, size_t size, size_t reading_size, uint8_t tag, uint32_t *saved_sum) |
| Restore a saved blob as store_restore does, and record the sum of the reading it holds. | |
| static time_t | store_poll_next (int poll_min, time_t now) |
| The next wall-clock second a poll of this interval falls due. | |
| static bool | store_poll_due (int poll_min, time_t *next, time_t now) |
Whether next has come round, moving it on to the following deadline when it has. | |
| static bool | store_poll_reconnect_due (int age_s, int poll_min) |
| Whether a reading is worth asking for again now that the phone is back. | |
| bool | store_poll_set (StorePoll *poll, int poll_min, bool live, time_t now) |
| Take a store's interval and whether it is live, as its init and its reconfigure both do. | |
| bool | store_poll_turn (StorePoll *poll, time_t now) |
| A store's turn on the face's cadence: whether a poll should go out now. | |
| uint32_t | store_sum (const void *bytes, size_t size) |
| Sums a run of bytes, so two readings can be compared without keeping both. | |
| void | system_store_init (SystemConfig cfg, const SystemSeed *seed) |
| Start the store with its rules. Pass seed = NULL for normal use. | |
| void | system_store_deinit (void) |
| Stop tracking the battery + connection services. | |
| void | system_store_subscribe (void(*cb)(void)) |
| Hand it the function to call when something changes (the screen redraw). | |
| void | system_store_on_reconnect (void(*cb)(void)) |
| Hand it the function to call when the phone app link comes back after a drop. | |
| int | system_store_battery (void) |
| How full the battery is from 0 to 100. | |
| bool | system_store_charging (void) |
| True while the watch is plugged in. | |
| bool | system_store_bluetooth (void) |
| True when the phone link is up. | |
| bool | system_store_next_alarm (time_t *out) |
| When the wearer's next enabled alarm fires. | |
| void | time_store_init (TimeConfig cfg, const struct tm *seed) |
| Start the store with its rules. Pass seed = NULL to start from the current time. | |
| void | time_store_reconfigure (TimeConfig cfg) |
| Re-apply the rules (e.g. the time format changed). Swaps the ticker to match. | |
| void | time_store_subscribe (void(*cb)(void)) |
| Hand it the function to call when the time changes (the screen redraw). | |
| const struct tm * | time_store_tm (void) |
| The time we hold right now. | |
| void | weather_store_init (WeatherConfig cfg, const WeatherSeed *seed) |
| Start the store with its rules. Pass seed = NULL for normal use. | |
| void | weather_store_reconfigure (WeatherConfig cfg) |
| Re-apply the rules (e.g. the poll interval changed). Moves the next poll to the new interval, and switching the store off here stops it asking the phone. | |
| void | weather_store_subscribe (void(*cb)(void)) |
| Hand it the function to call when the weather changes (the screen redraw). | |
| int | weather_store_temp (void) |
| The temperature reading in the user's unit, or WEATHER_NO_TEMP if we have not got one yet. | |
| const char * | weather_store_cond (void) |
| The short word for the sky, or empty if we have not got one yet. | |
| const char * | weather_store_cond_label (void) |
| The sky in words, such as "Partly Cloudy", for a face that declares WEATHER_CONDITION_LABEL. | |
| int | weather_store_humidity (void) |
| The humidity in percent, or -1 if we have not got one yet. | |
| int | weather_store_wind_kmh (void) |
| The wind speed in km/h, or -1 if we have not got one yet. | |
| const char * | weather_store_wind_dir (void) |
| The wind direction like "NW", or empty if we have not got one yet. | |
| int | weather_store_sunrise (void) |
| Sunrise as minutes past midnight, or -1 if we have not got one yet. | |
| int | weather_store_sunset (void) |
| Sunset as minutes past midnight, or -1 if we have not got one yet. | |
| int | weather_store_feels_like (void) |
| How warm it feels, or WEATHER_NO_TEMP if we have not got one yet. | |
| int | weather_store_pressure (void) |
| The sea level pressure in hPa, or -1 if we have not got one yet. | |
| int | weather_store_dew_point (void) |
| The dew point temperature, or WEATHER_NO_TEMP if we have not got one yet. | |
| int | weather_store_uv (void) |
| Today's UV index, or -1 if we have not got one yet or the day it came is over. | |
| int | weather_store_temp_max (void) |
| Today's high, or WEATHER_NO_TEMP if we have not got one yet or the day it came is over. | |
| int | weather_store_temp_min (void) |
| Today's low, or WEATHER_NO_TEMP if we have not got one yet or the day it came is over. | |
| int | weather_store_precip_chance (void) |
| Today's chance of rain in percent, or -1 if we have not got one yet or the day it came is over. | |
| const WeatherHourly * | weather_store_forecast_hourly (void) |
| The hourly forecast strip, starting at the hour now. | |
| const WeatherDaily * | weather_store_forecast_daily (void) |
| The daily forecast strip, starting today. | |
| int | weather_store_age_s (void) |
| How many seconds since the last reading turned up, or -1 if we have none. | |
Weather, health, calendar, stocks, and the other readings a face shows.
Each store keeps its reading fresh and nudges the screen when it changes.
| #define STORE_READING_SIZE | ( | state, | |
| stamp ) |
How many leading bytes of a store's blob are the reading, which is everything before its sync time.
| state | The store's blob. |
| stamp | The name of its sync time field, which has to come after every reading. |
| #define WEATHER_SEED_EMPTY |
A WeatherSeed with every optional reading already set to its no-data value. Spread it and override only what you have, so a partial seed still reads as "--" instead of a bogus 0. Copy it from a named static const, which the linker drops with the dev code in a release build. Written straight into a local, it leaves an unnamed copy in .data that every build keeps.
| typedef void(*) BtVibePolicy(bool connected) |
Called on a real bluetooth transition (a change, not the first reading), so the face can buzz however its own settings say. NULL for a silent link change.
| connected | True when the link just came up, false when it just dropped. |
| const CalendarEvent * calendar_store_event | ( | uint8_t | index | ) |
One event by index, or NULL when the index is past what is filled.
| index | Which event to read (0 based). |
| void calendar_store_init | ( | CalendarConfig | cfg, |
| const CalendarSeed * | seed ) |
Start the store with its rules. Pass seed = NULL for normal use.
| cfg | The rules (live / poll interval). |
| seed | Optional prefill, or NULL. |
| void calendar_store_reconfigure | ( | CalendarConfig | cfg | ) |
Re-apply the rules (e.g. the poll interval changed). Moves the next poll to the new interval, and switching the store off here stops it asking the phone.
| cfg | The new rules. |
| void health_store_init | ( | HealthConfig | cfg, |
| const HealthSeed * | seed ) |
Start the store with its rules. Pass seed = NULL for normal use.
| cfg | The rules (live). |
| seed | Optional prefill, or NULL. |
| void location_store_init | ( | LocationConfig | cfg, |
| const LocationSeed * | seed ) |
Start the store with its rules. Pass seed = NULL for normal use.
| cfg | The rules (live / persist_key). |
| seed | Optional prefill, or NULL. |
| void stock_store_init | ( | StockConfig | cfg, |
| const StockSeed * | seed ) |
Start the store with its rules. Pass seed = NULL for normal use.
| cfg | The rules (live / poll interval). |
| seed | Optional prefill, or NULL. |
| void stock_store_reconfigure | ( | StockConfig | cfg | ) |
Re-apply the rules (e.g. the poll interval changed). Moves the next poll to the new interval, and switching the store off here stops it asking the phone.
| cfg | The new rules. |
| const StockSlot * stock_store_slot | ( | uint8_t | index | ) |
One slot by index, or NULL when the index is past what is filled.
| index | Which slot to read (0 based). |
| void store_cadence_register | ( | void(* | cb )(void) | ) |
Ask for cb to run each time the face's cadence comes round. A store calls this from its own init, so no face has to wire it up by hand.
The cadence is whichever ticker the face runs: the minute tick, or the .beats timer in its place. A face with neither never fires this, so put periodic work here, not work something depends on. Registering the same function twice does nothing.
| cb | The work to run. NULL is ignored. |
| void store_fetch_arm | ( | StoreFetch * | fetch | ) |
Arm the one-shot fetch after first_ms, unless one is already waiting.
| fetch | The store's fetch state. |
| void store_fetch_fire | ( | void * | data | ) |
The one-shot fetch's timer callback. Clears the timer and asks the phone.
| data | The StoreFetch the timer was armed for. |
| void store_fetch_reconfigure | ( | StoreFetch * | fetch, |
| int | poll_min, | ||
| bool | live, | ||
| time_t | now, | ||
| bool | empty ) |
What a store's reconfigure does with its polling.
Switching the store off clears the live flag, which stops the cadence turn too, and drops any fetch still waiting. A store that keeps polling keeps its launch fetch, since a settings push that lands in the first second would otherwise cancel it and leave a restored reading stale until the next deadline.
An empty store has nothing to draw, so it catches up right away. One that already holds data waits for its deadline, so a save that only touched colours does not fetch on the spot and spend a metered provider's quota. That deadline is a wall-clock boundary, so a save can bring it nearer but never past the interval's rate.
| fetch | The store's fetch state. |
| poll_min | Minutes between polls. 0 or less means no polling. |
| live | True on a live face. |
| now | The current wall-clock time. |
| empty | True when the store holds nothing to show yet. |
| void store_fetch_start | ( | StoreFetch * | fetch, |
| int | poll_min, | ||
| bool | live, | ||
| time_t | now ) |
What a store's init does with its polling. Takes the interval, then arms one fetch shortly after launch when polling is on, so the store is not blank while the first deadline is coming.
| fetch | The store's fetch state. |
| poll_min | Minutes between polls. 0 or less means no polling. |
| live | True on a live face. |
| now | The current wall-clock time. |
| void store_fetch_stop | ( | StoreFetch * | fetch | ) |
Cancel the one-shot fetch, if one is armed.
| fetch | The store's fetch state. |
| void store_fetch_turn | ( | StoreFetch * | fetch, |
| time_t | now ) |
The store's turn on the face's cadence. Asks the phone when the deadline has come round.
| fetch | The store's fetch state. |
| now | The current wall-clock time. |
|
inlinestatic |
Whether next has come round, moving it on to the following deadline when it has.
A clock that jumps forward just fires once and carries on. One that jumps back would strand the deadline more than an interval ahead, so that case is pulled back in.
| poll_min | Minutes between polls. 0 or less means polling is off and this is never due. | |
| [in,out] | next | The store's deadline, read and updated in place. |
| now | The current wall-clock time. |
|
inlinestatic |
The next wall-clock second a poll of this interval falls due.
Counted from the epoch rather than from launch, so two watches started minutes apart poll at the same moments and a relaunch does not shift the phase.
| poll_min | Minutes between polls. Must be above 0. |
| now | The current wall-clock time. |
|
inlinestatic |
Whether a reading is worth asking for again now that the phone is back.
The phone's side may have been closed the whole time it was away, so a face catches up a reading that went stale meanwhile. Only a reading that never arrived, or one at least its own interval old, is asked for, so bluetooth dropping in and out cannot fetch faster than the normal polling. Polling turned off is left alone, the same as its store.
| age_s | Seconds since the reading arrived, or below 0 when it never has. |
| poll_min | Minutes between polls. 0 or less means polling is off. |
| bool store_poll_set | ( | StorePoll * | poll, |
| int | poll_min, | ||
| bool | live, | ||
| time_t | now ) |
Take a store's interval and whether it is live, as its init and its reconfigure both do.
Both are always recorded. The deadline only moves when polling is on, and then to the next interval boundary, so a save can bring a poll nearer but never make one come faster than the interval allows.
| [in,out] | poll | The store's polling state. |
| poll_min | Minutes between polls. 0 or less turns polling off. | |
| live | Whether the store is live. | |
| now | The current wall-clock time. |
| bool store_poll_turn | ( | StorePoll * | poll, |
| time_t | now ) |
A store's turn on the face's cadence: whether a poll should go out now.
| [in,out] | poll | The store's polling state. The deadline moves on when a poll is due. |
| now | The current wall-clock time. |
|
inlinestatic |
Restore a saved blob into state, but only when it is this store's own current layout.
Checks the size and then the tag byte. Nothing is written into state unless both match, so the defaults the caller applied before calling survive a rejected blob.
| key | The persist slot the face handed the store. | |
| [out] | state | The struct to fill. Its first field must be the uint8_t tag. |
| size | sizeof that struct. | |
| tag | The store's STORE_TAG_* value. |
| bool store_restore_reading | ( | uint32_t | key, |
| void * | state, | ||
| size_t | size, | ||
| size_t | reading_size, | ||
| uint8_t | tag, | ||
| uint32_t * | saved_sum ) |
Restore a saved blob as store_restore does, and record the sum of the reading it holds.
The sum is what store_save_changed compares against, so a first reply bringing the same reading after a relaunch is not written again.
| key | The persist slot the face handed the store. | |
| [out] | state | The struct to fill. Its first field must be the uint8_t tag. |
| size | sizeof that struct. | |
| reading_size | How many leading bytes are the reading, from STORE_READING_SIZE. | |
| tag | The store's STORE_TAG_* value. | |
| [out] | saved_sum | The sum of the restored reading, or 0 when nothing was restored. |
|
inlinestatic |
Save a store's blob with its tag stamped in, so the next restore can recognize it.
| key | The persist slot the face handed the store. | |
| [in,out] | state | The struct to write, with its tag stamped in on the way. Its first field must be the uint8_t tag. |
| size | sizeof that struct. | |
| tag | The store's STORE_TAG_* value. |
| bool store_save_changed | ( | uint32_t | key, |
| void * | state, | ||
| size_t | size, | ||
| size_t | reading_size, | ||
| uint8_t | tag, | ||
| uint32_t * | saved_sum ) |
Save a store's blob only when its reading is different from what is already on flash.
Only the first reading_size bytes are compared, so a reply that brings the same reading with a new sync time writes nothing. The flash copy then keeps the sync time of the last real change, and a relaunch reads the reading as older than it is. The catch-up poll after a reconnect fires a little sooner for it, which costs one request at most.
| key | The persist slot the face handed the store. | |
| [in,out] | state | The struct to write, with its tag stamped in on the way. Its first field must be the uint8_t tag. |
| size | sizeof that struct. | |
| reading_size | How many leading bytes are the reading, from STORE_READING_SIZE. Pass the whole size for a blob with no sync time. | |
| tag | The store's STORE_TAG_* value. | |
| [in,out] | saved_sum | The sum of the reading last written, which the store keeps. It moves on only when a write lands. |
| uint32_t store_sum | ( | const void * | bytes, |
| size_t | size ) |
Sums a run of bytes, so two readings can be compared without keeping both.
FNV-1a, which mixes each byte in turn. A plain byte total would miss two values swapping places, and a reading that only reordered its forecast would never be saved.
| bytes | The bytes to sum. |
| size | How many there are. |
| void system_store_init | ( | SystemConfig | cfg, |
| const SystemSeed * | seed ) |
Start the store with its rules. Pass seed = NULL for normal use.
| cfg | The rules (live / vibe policy). |
| seed | Optional prefill, or NULL. |
| bool system_store_next_alarm | ( | time_t * | out | ) |
When the wearer's next enabled alarm fires.
Read through to the alarm service on every call, since there is nothing to subscribe to. A platform without the alarm API always reads as no alarm.
| [out] | out | Set to the alarm's UTC time, or 0 when there is none. Never NULL. |
| void time_store_init | ( | TimeConfig | cfg, |
| const struct tm * | seed ) |
Start the store with its rules. Pass seed = NULL to start from the current time.
| cfg | The rules (live / cadence). |
| seed | Optional time to pin (dev/screenshots), or NULL for the current time. |
| void time_store_reconfigure | ( | TimeConfig | cfg | ) |
Re-apply the rules (e.g. the time format changed). Swaps the ticker to match.
| cfg | The new rules. |
| const char * weather_store_cond_label | ( | void | ) |
The sky in words, such as "Partly Cloudy", for a face that declares WEATHER_CONDITION_LABEL.
| const WeatherDaily * weather_store_forecast_daily | ( | void | ) |
The daily forecast strip, starting today.
Days before today come off the front as it is read, and base_weekday moves with them.
| const WeatherHourly * weather_store_forecast_hourly | ( | void | ) |
The hourly forecast strip, starting at the hour now.
A strip can outlive the fetch that brought it, when only the forecast half of a later fetch fails. Columns whose hour is over come off the front as it is read, and base_hour moves with them, so a column is never labelled with an hour already gone.
| void weather_store_init | ( | WeatherConfig | cfg, |
| const WeatherSeed * | seed ) |
Start the store with its rules. Pass seed = NULL for normal use.
| cfg | The rules (live / poll interval). |
| seed | Optional prefill, or NULL. |
| void weather_store_reconfigure | ( | WeatherConfig | cfg | ) |
Re-apply the rules (e.g. the poll interval changed). Moves the next poll to the new interval, and switching the store off here stops it asking the phone.
| cfg | The new rules. |