Files
pigway-frame-flow/docs/research/KOKONNA_CONTENT_SUBSCRIPTIONS.md
T

116 lines
11 KiB
Markdown
Raw Normal View History

# KoKonna official content and subscriptions
Checked 2026-10-02 against official public sources:
- Product: https://kokonna.art/products/kokonna-ai-e-ink-frame-7
- Chinese FAQ: https://kokonna.art/zh-hans/pages/常见问问题
- OpenAPI: https://kokonna.art/pages/openapi
Official product materials list calendar/local weather, word of the day, traditional almanac, global travel recommendations and daily news. FAQ also lists image rotation and AI art modes (voice, text, sketch, photo style transformation). These product/widget categories are not a verified complete catalog of current mainland WeChat mini-program subscriptions. The user's daily-poetry subscription is firsthand evidence of that option; public materials reviewed do not document its subscription contract.
The current OpenAPI documents device, upload, listImages, deleteImage, image retrieval, displayImageById and displayImageByName. Device metadata includes rotation mode/interval and current image/cover; it does not document selected subscription IDs or original template data. No subscription catalog/read/create/update/cancel interface is listed. Therefore an official subscription integration is blocked on a documented provider contract, not on a Frame Flow rendering limitation.
Frame Flow displays official categories and explicit unsupported status, with links to original docs. It does not present its own poetry provider as the official subscription, fabricate endpoints, infer subscription from an image, or alter existing official subscriptions. A future documented API should be implemented in the KoKonna driver, preserving the public capability model, rather than through vendor-specific core behavior.
To complete official integration: obtain a current mini-program subscription-page screenshot/catalog and official subscription API documentation (endpoint, auth type, schema, effect of writes). Credentials or session tokens must not appear in screenshots or documentation. No private endpoint guesses or authenticated cloud writes were used in this investigation.
## Follow-up: widgets versus public API (2026-10-02)
Further investigation after the user confirmed the mini-program can read the selected widget:
- Official usage guide https://kokonna.art/pages/how-to-use calls these **Smart Widgets**. Step 04 describes selecting Weather, News or Calendars and automatic midnight refresh. This confirms official selection/refresh functionality; it does not document the underlying request paths or authentication.
- Manufacturer site https://www.galaxyguide.cn/ confirms weather/calendar widgets and slideshows.
- Additional reference https://kokonna.art/zh-hans/pages/openapi_cn fetched HTTP 200. Its documented device/image endpoints contain no widget/subscription configuration contract.
- GitHub `patrickchen914/kokonna`, inspected `custom_components/kokonna/const.py`, `__init__.py`, `select.py`: uses galaxyguide OpenAPI gallery/image switching. No widget configuration implementation found in these files.
- GitHub `nixihz/kokonna-skill`, inspected `kokonna/client.py` and README: exposes public image/device endpoints; no widget/subscription calls found.
- NPM lookup for `@guooscar/kokonna-frame` returned HTTP 404 during this follow-up; it cannot provide current independently retrievable endpoint evidence. Earlier protocol-reference findings remain historical.
**Correct interpretation:** public API documentation does not list widget/subscription configuration endpoints. This is not evidence that the official client lacks internal APIs. Since the mini-program displays selected configuration, some official client/backend mechanism provides it; a separate authenticated internal API is plausible but remains an inference. No actual widget endpoint name, HTTP method, request/response schema or authorization model has yet been verified. Do not label the integration impossible merely because it is undocumented.
Next verification should observe the user's own authorized mini-program read requests when opening widget selection/current-widget settings. Capture only the necessary request path, method and sanitized JSON; do not export login tokens, cookies or full network archives. Begin with read-only inspection and keep subscription mutations separate. The public device API key must not be assumed equivalent to mini-program user authentication.
## Direct client evidence: official Android 1.6.5
The official download page https://kokonna.art/pages/download-app links `nightly_build_1.6.5.apk` from its own CDN. Downloaded for static inspection only; not installed or executed. APK bytes: 23,149,381. SHA256: `8f611bf74bbda70e7e7a5d087e4065dc6000849dcd2f12538d5ff5017c91e1c0`. Evidence resides in `assets/apps/__UNI__2C90476/www/app-service.js`. No vendor source or APK is committed to this repository.
**Found transport:** `POST https://robot.galaxyguide.cn/api/rpc`, JSON-RPC 2.0, envelope `jsonrpc`, `method`, `params`, `id`; result at `result`. Authorization is Bearer **official user session token** from login/storage, not proven compatible with OpenAPI device key.
| Client method | Parameters seen | Evidence / use |
| --- | --- | --- |
| `appFrame.getFrameCovers` | `robotId` | Widget selection page; reads `robot`, `rows`, `tags`, `frameCoverRobot`. |
| `appFrame.getFrame` | `id` | Device detail; reads `robot`, `frameImage`, `imageCount`, sync metadata. |
| `app.getRobots` | See client/device discovery; schema still to verify | User device discovery. |
| `appFrame.setFrameCover` | `robotId`, `coverId`, optional `args` | Selects/configures widget. WRITE: not executed. |
| `appFrame.setFrameCover` | `robotId`, `coverId: null` | Removes current widget. WRITE: not executed. |
Current widget is explicitly determined from `frameCoverRobot.frameCover.id`; user configuration comes from `frameCoverRobot.args`. UI compares selected rows with `robot.frameCoverRobot.coverId`. Therefore the mini-program-style current-template capability has a concrete client contract, not merely an image-ID inference.
Client category keys: Weather (天气), Lunar (农历), Calendar (单向历), Countdown (倒计时), Stopwatch (正计时), DailyRandom (推送), plus feature/current filters. Specific poems/news/etc. are server-provided `rows` names, not an exhaustive hardcoded list. The daily-poetry item cannot be mapped to a numeric cover ID until authenticated directory data is read.
Authentication paths observed: `app.login` with username/password; `app.wxlogin` with WeChat login code returns user token. Frame Flow login account is unrelated. App code alone does not prove Android and WeChat versions use identical methods, nor guarantee this private API stays compatible.
No authenticated requests or live widget writes were sent. Next step is official-account read-only verification of device discovery and `getFrameCovers`; requires legitimate official session/account access. Keep session secret server-side and out of logs, front-end, SQLite plaintext, and Git. Device-key compatibility was subsequently tested with explicit user authorization; see the verification below.
## Live WeChat verification (2026-10-02)
With explicit user authorization, a temporary localhost observer chained through the existing VPN proxy at 127.0.0.1:7890. Only robot/api.galaxyguide.cn were routed to the observer; other domains and original bypass entries retained their prior routing. Mutating RPC calls were blocked. An automatic three-minute rollback disabled/removed the PAC configuration and removed certificate trust.
Observed the user's own WeChat mini-program send `appFrame.getFrame` (parameter key `id`) and `appFrame.getFrameCovers` (parameter key `robotId`) to the RPC transport. The latter returned `frameCoverRobot`, `tags`, `rows`, `robot`. **75 widgets** were returned; sanitized IDs/names/categories and argument names are retained in `KOKONNA_WIDGET_CATALOG.json`. No user session, device key, account credentials, photos, device IDs or actual argument values are retained.
The selected-widget metadata extractor returned null for cover ID/name during this session. This alone is insufficient to conclude the device has no widget: current-selection shape/actual state requires another focused verification. The directory's 古诗词名句 has ID 29; this must not be assumed equivalent to the user's described 每天一首诗词 without checking the actual selected item.
Cleanup verified: PAC URL `(null)`, disabled; zero observer CA certificate entries in System keychain; observer terminated; private CA files removed; user session only existed in process memory and was discarded. Original HTTP/HTTPS/SOCKS proxy remains 127.0.0.1:7890. No official subscription/upload/display/delete writes were sent. Other NAS services and VPN application configuration were untouched.
Integration is now technically supported by live read evidence, not blocked on interface discovery. Remaining work is authenticated current-selection verification and an explicit maintainable official-session login/renewal strategy. Do not silently persist the captured WeChat session or commit it as configuration. Official RPC is undocumented and may change independently of OpenAPI.
## Read-only integration implemented
`GET /api/v1/devices/{device_id}/widgets` returns a typed catalog, source
(`live`, `snapshot`, `mock`), configuration status and verified current selection.
The template page provides searchable official widgets, separately from local
Frame Flow templates. Missing credentials show the 2026-10-02 observed catalog
of 75 entries; this is explicitly a snapshot, never a live subscription claim.
For an authorized official session, configure a device in `config/devices.yml`:
```yaml
devices:
living-room:
driver: kokonna
api_key_env: KOKONNA_API_KEY
widget_token_env: KOKONNA_WIDGET_TOKEN
widget_robot_id: 123 # replace with the official internal robot ID
enabled: true
```
Supply `KOKONNA_WIDGET_TOKEN_FILE` pointing to a protected mounted secret file,
or inject `KOKONNA_WIDGET_TOKEN`. This credential is a separate official user
session, not the OpenAPI device key or Frame Flow login password. No observed
WeChat session has been persisted. Sessions may expire; there is no automatic
WeChat login or refresh implementation yet. Successful reads are cached for
60 seconds. Raw robot data, token-bearing URLs and argument values are omitted.
Only `appFrame.getFrameCovers` is callable by this integration. Widget selection,
subscription mutation and cancellation are not implemented or executed. A null
or unmatched current selection returns `CURRENT_UNVERIFIED`, not “no subscription”.
This private RPC contract is unofficial and may change independently of OpenAPI.
## Device API Key compatibility verification (2026-10-02)
At the user's explicit request, performed exactly three read-only calls from the
NAS using the configured device API Key, without logging or persisting the key:
| Query | HTTP | Result |
| --- | --- | --- |
| OpenAPI `/device` | 200 | Device key accepted |
| RPC `app.getRobots` | 500 | JSON-RPC error code -1, 请重新登陆 |
| RPC `appFrame.getFrameCovers` | 500 | JSON-RPC error code -1, 请重新登陆 |
No RPC result was returned, and no uploads, display changes or subscription
mutations were performed. The valid OpenAPI device key was not accepted as an
official account session by these RPC methods. This confirms the distinction
for the currently observed endpoints; it does not prove all future widget APIs
will require a WeChat-specific session. An official account login session may
also be supported, but has not been verified here.