codewatch docs plugins.md
7.9 kB · 92 lines
Markdown
at main

Plugins #

Plugins (branch plugins, 2026-11-06) #

Status lines can show readings from Pebble plugins (2026-11-06: one dropdown, include favourites, build now even though store publishing of plugin consumers isn't open yet). Guide: developer.repebble.com/guides/plugins/preview/; reference consumers are Core's complication-face and plugin-test in github.com/coredevices/pebble-apps. Kept independent of the workspace's homeassistant/ plugin: test against built-in sources.

  • Needs SDK 4.44: pebble build --sdk 4.44 (4.33.1 stays the workspace's active SDK). Only 4.44's waf writes manifestVersion: 2 and usesPermissions into appinfo.json; without them the phone treats the app as legacy, enumeratePlugins() returns nothing and every subscription fails PERMISSION_DENIED. 4.44 declares SDK rev 0x6e (5.110), so the minimum firmware is v4.44.3 (from pebbleOS tags, 2026-11-06: v4.43.0–v4.44.2 are 0x6d, v4.44.3/4 0x6e, v4.45.0 0x6f; 2.3 needed v4.32.0). The rise was a deliberate call, 2026-11-06.
  • Phones without plugins (plugins.state()): an app before 1.16 has no plugin functions (absent); a current app with plugins switched off keeps the functions, but enumeratePlugins() lists nothing (not even the built-ins) and every subscription answers PLUGIN_UNAVAILABLE (off; a test phone, 2026-11-06). Either way no Plugin reading and no favourites are offered, and a line already set to one reads update Pebble app / turn on plugins. The state is read when the phone JS starts, so switching plugins back on shows at the next face relaunch. The settings page then shows a red-outlined note above the credit line (pluginhelp text item, filled from userData.pluginHelp by the customFn): > plugins are off with where to switch them on, or > plugins need a newer Pebble app. Only while a line is set to Plugin reading or a favourite; it follows the dropdowns live. Chromium-checked with the note injected (the emulator always has plugins on). Permissions are only enforced when plugins are enabled (guide), so weather behaves as before for them.
  • Store status (2026-11-06): the guide (app 1.17.0.1) still says "Don't ship anything that uses/offers plugins to the app store yet" and calls the API unstable; Core's own demo consumers are in the store, third-party plugin publishing is invite-only. pebble-tool's publish has no gate for consumers.
  • Manifest v2 means declaring what the JS uses: Location (weather's geolocation, and weather sources), Internet for api.open-meteo.com, plus Calendar and ReadMusic so the calendar and music sources can be offered. Add any new host here or the phone blocks it.
  • The picker offers only sources we have permission for. enumeratePlugins() reports each source's callerPermissions; plugins.js reads usesPermissions from package.json and skips any source needing more. The emulator only logs missing grants (pypkjs _log_grants) and serves the data anyway, so without this filter Watch Settings (ReadWatchSettings) and Notifications (Notifications) showed up and would have read needs permission on a phone. To offer one, declare its permission. Each source is capped at 60 things.
  • First run after install: weather failed twice (Location permission not granted, then HTTP 403 from the phone) until the phone granted the declared permissions, then recovered via the backoff a few minutes later (the test watch, 2026-11-06). Expected, per the guide: requests fail until the permission is answered.
  • Settings (two-step picker, 2026-11-06, after build 20's flat list was "crazy overcrowded"): each line's dropdown gets Pebble favourite 1–3 (StatusField 18–20: the readings ranked in the Pebble app, preferences/complications) and, when any plugin has readings, Plugin reading (17). A line set to Plugin reading shows two more selects under it:
    • from: one entry per thing (a source instance), in optgroups by plugin (Weather · location only when a plugin has several sources). Named things by name (London); positional sources (every instanceId equals its index: calendar events, weather hours) are slots, so event 1 (Design review); an unnamed one among several is hour 3; the only one is its item (phone state). Page-only, no messageKey.
    • shows: that thing's text-drawable properties (shortText, numericValue, boolean, timestamp; not name) with live values, high: 14°C. messageKey PluginPick1–3. index.js runs Clay with autoHandleEvents: false: on open, plugins.catalogue() subscribes to every source for up to 4 s and returns {groups, readings}; the options go into the config and readings into meta.userData, and the customFn shows/hides the pair and refills "shows" from userData.readings when "from" changes (raw DOM on pick.$manipulatorTarget[0], then trigger('change') to update Clay's value label). A picked reading whose plugin is gone stays as Unavailable / plugin reading, or Plugins off / plugin reading › turn on plugins (Plugins unsupported … › update Pebble app on an old app), matching what the watch shows. Checked in headless Chromium: cascade, hiding, save.
  • Not offered: preferences and agent categories, and items named configured (Core's demo plugins use them as a set-up flag), besides anything we lack permission for (below).
  • A picked reading is stored in Clay's settings as PluginPickN = p|plugin|category|item|instanceId|property (parts URI-escaped). webviewclosed deletes the PluginPick keys before sending, so the watch only gets FIELD_PLUGIN (17). Build 20 stored the key in FieldN itself; opening the page migrates it, and plugins.js reads either.
  • The phone formats, the watch draws (src/pkjs/plugins.js): name value in 17 characters, label shortened first, at a word break when that leaves ≥3 characters (Design 22:00); an unnamed instance among several is item N (hour 3 20°C); only ASCII, °, · survive (accents dropped). Instance missing → not found, PERMISSION_DENIED → needs permission, PLUGIN_UNAVAILABLE → plugin missing, other errors keep the last text. Sent as PluginLine1–3.
  • Rate limit (every AppMessage holds BLE fast for 10 s): 2 s debounce, then only on change, at most every 5 min (the latest value wins), plus an hourly resend of an unchanged line. The last delivered texts live in localStorage (pluginSent), so a face relaunch sends nothing. Saving settings sends at once. Node-simulated with a fake clock, 2026-11-06.
  • Plugin lines stay white (2026-11-06): colour in the status area means something (steps vs goal, battery charge), and a plugin's value carries no such meaning.
  • Watch side: persist key 400 (PluginLines: per line, the text and when it arrived). waiting for phone until the first text, no plugin data after 2 h. A settings message that touches a plugin line clears its text.
  • Emulator (4.44 emery, 2026-11-06): built-ins offered are Phone, Calendar, Watch Settings, Music, Notifications, Weather. There's no Preferences plugin there, so favourites read no favourite N (which also caught a bug: lines waited on favourites before subscribing). Verified: catalogue, save, Palo Alto 18°C / battery level 87% on the face, no resend on relaunch, weather still fetched with permissions declared. Gabbro only built, not run.
  • Wrist-only questions: whether favourites fill in (no Preferences plugin in the emulator); whether the phone prompts for Calendar/ReadMusic at install or on first use; whether the Clay page loads normally for a manifest v2 app. The first wrist run showed the page loading and readings arriving.