Status: preview. The Glassly OEM Integration Engine covers the full surface
documented below. The runtime is not yet packaged for external install —
reach out to [email protected] to integrate today.
What it is
The Glassly OEM Integration Engine is the API an OEM host app (the phone-side app that talks to your glasses) calls to run Glassly. It ships as the@glassly/engine module and
exposes a single namespaced object, engine:
- The host owns UI, navigation, and login. Your screens, your router, your auth.
- The engine owns the runtime and the device. Connection, device state, wifi, on-device speech models, the display pipeline, the miniapp runtime.
engine.<domain>.<method>() for everything
device- and runtime-related. The engine is device-agnostic: the same calls work
across glasses models.
Lifecycle
The host hands the engine its auth + config once, then starts it.auth.getSubjectToken() is the only must-have seam — the host owns login and returns
a fresh token on demand; the engine owns everything downstream.
engine.glasses
Connection actions, a curated status/info read-model, capabilities, version, and the
discrete input events.
Connection
Status & info (read-models)
status() returns a snapshot projected from the runtime’s glasses store, in a stable
shape that doesn’t leak the internal store layout:
Input events
on*() returns an unsubscribe function.
engine.glasses.wifi
connect() propagates the bluetooth layer’s coded errors (bluetooth_powered_off,
request_timeout, …) unchanged, so your UI keeps its own error mapping.
engine.glasses.settings
Keyed device settings (brightness, head-up angle, dashboard, camera/button,
sensing, …). set() persists and auto-syncs to the connected glasses.
available() is the authoritative list at runtime (it varies by model/capabilities).
The current keys, their types, and defaults:
Device identity (paired-device id/name/address, controller address) and internal
runtime flags (e.g. STT-fallback state) are intentionally not in this surface —
read the connected device via
engine.glasses.info().engine.pairing
First-time glasses discovery + pairing. (Reconnecting the already-paired default is
engine.glasses.connectDefault().)
engine.speech
On-device STT/TTS model management.
engine.display.mirror
A typed read facade for a phone-side preview of the glasses screen.
Scene rendering, shapes, and the canvas
Miniapps draw through the engine’s scene API; the engine rasterizes or translates each frame for the connected device. Two things vary by firmware, and both are read off the device’s effective capabilities rather than hard-coded. Vector shapes. Firmware that draws vectors declaresrect · circle · arc · pie · line · triangle · quad · bezier, plus svg on Glassly
CFW. Elements carry a style — border/fill/radius on closed shapes, width on
open strokes (line, bezier, arc) — and a gray color. Devices without vector support
render scenes through the host degrade path instead.
Intensity. The baseline is 4-bit grayscale: every drawable’s color is a gray level
0–15, where 15 is brightest and 0 means “not drawn”. Stock G2 firmware reports
intensityLevels: 2; CFW reports the full ramp.
Animation. An element with a stable id can carry a transition
({durationMs, easing}, easing one of linear · ease · ease-in · ease-out · ease-in-out).
The device tweens the geometry change itself when its capabilities declare animation;
on images the tween reads as a fade. rotation is a separate capability covering
geometric and SVG rotations.
Depth. Devices with two lenses may declare depth: per-element depth (a
disparity of -16..16 canvas px) is then drawn depth px further right on the left
lens and further left on the right, so positive values float in front of the frame.
Glassly CFW declares it and sends each lens its own object-cache SHOW once a frame
uses depth. Devices without it draw every element flat; depth never drops anything.
Canvas negotiation. The drawable canvas is not fixed. 576×288 is the pre-report
fallback — the stock G2 scene canvas, which firmware blits 1:1 into the 640×480 panel.
Glassly CFW rasterizes scenes phone-side straight into the panel and publishes its real
canvas in the glasses status; the engine then overrides the model profile with the
reported size. Because CFW frames are not bound by the stock container pools
(6 text / 4 image), element budgets are lifted alongside the canvas: 24 text / 16
image on a raster CFW build, and 120 shared elements on a CFW build that reports
vector support (shapes and images each cost one cached slot, so shape-heavy frames get
one larger budget).
Read the budgets and canvas from
engine.glasses.capabilities() at runtime. They change
when the glasses reconnect with different firmware — never bake 576×288 or the stock
pools into a host.engine.session
The cloud (cloud-v2) live-session surface. engine owns the cloud client — it
constructs it from engine-owned transports + the auth you passed to
configure() — so this reads the session it manages.
status is one of connected | connecting | reconnecting | disconnected;
audioTransport is udp | ws | offline | none.
engine.settings
Typed keyed user settings over the engine-owned settings store.
engine.reports
Bug report and feedback submission. The OEM writes its own report screen,
trigger labels, rating controls, and screenshot picker UX; engine owns runtime
context collection, recent phone logs, Cloud V2 submission, artifact upload,
dedupe, and glasses notification.
engine.dev
Developer/debug surface — backend + cloud-v2 URL overrides, reconnect, version gate.
engine.permissions
OS permissions — the raw check/request ops (your UI adds the rationale dialogs).
microphone · camera · calendar · location · background_location · bluetooth · phone_state · post_notifications.
engine.phoneNotifications
Forward phone notifications to the glasses, with a per-app blocklist. Android-only
(getters return safe defaults on iOS).
engine.notifications
Inbound alerts engine→host — conditions engine detects, your UI renders.
engine.ota
Firmware OTA. Engine owns availability checks and install orchestration; the host
progress screen is a pure renderer over the coordinator snapshot.
engine.ota.installSession fronts the install state machine for a progress screen:
prepare(result), attach(), detach(), retry(), finish(), discard(),
snapshot(), onSnapshot(cb). Every watchdog, retry, and reconnect rule lives in the
coordinator — the screen only renders the snapshot.
engine.gallery
Gallery sync (hotspot → wifi → HTTP fetch → process → store). Engine orchestrates;
the host renders its own alerts and navigation off onNotice.
engine.miniapps
Miniapp lifecycle. The miniapp WebView is a host component — engine ships the
bridge primitives (buildMiniappGlobalsScript, buildUiShim, the JSRuntime
router), exported from @glassly/engine directly; your app mounts the <WebView> and
wires it to those. This facade is the lifecycle half.
What the host provides
The boundary is small and explicit: the host provides its UI, its login, and optional config — engine owns the entire runtime. The only required seam isauth.getSubjectToken (passed to configure()); engine owns token exchange, refresh,
storage, the cloud client, glasses/BLE, settings, speech, display, and the miniapp
runtime from there.
You may see internal
configureRuntime(...) wiring in the first-party Glassly App —
that’s transitional scaffolding for migrating Glassly’s own screens, not part of
the OEM contract. It deletes itself as each domain lands in engine. An OEM only ever
calls configure({auth, config?}) + start().
