数据与客户端 API
公共类型以包内 vendor/ride-ui-sdk/dist/client.d.ts、contract.d.ts 为准;完整遥测键见导出的 RIDE_UI_TELEMETRY_KEYS_V1。主题运行时代码只导入 client 和 contract,replay 仅供开发调试。
客户端生命周期
import { createRideUiClient } from '@motexa/ride-ui-sdk/client'
import type { RideUiInitContextV1 } from '@motexa/ride-ui-sdk/contract'
const client = createRideUiClient('partner.example-dashboard')
let context: RideUiInitContextV1 | null = null
client.subscribeContext(next => { context = next })
client.subscribeDisplayFrame(frame => {
const text = frame.speedKmh == null ? '--' : frame.speedKmh.toFixed(0)
console.log(text, frame.state)
})
client.ready()
async function refresh() {
if (!context?.capabilities.includes('ride.refresh')) return
const result = await client.requestAction('ride.refresh')
if (!result.ok) console.log(result.error?.code)
}
// 页面或组件卸载时调用 client.dispose()。
一个主题实例使用一个客户端。订阅方法返回取消订阅函数。SDK 处理 theme.ready → host.init 的握手和后续消息会话;不要自行复刻桥接。会话标识仅用于消息隔离。
| 方法 | 用途 |
|---|---|
ready() |
通知宿主主题已准备好 |
subscribeContext(listener) |
模式、语言、配色、安全区域、能力、配置与初始快照 |
subscribeSnapshot(listener) |
完整场景和标准遥测快照 |
subscribeFrame(listener) |
高频速度、功率和部分遥测 |
subscribeDisplayFrame(listener) |
宿主速度显示帧 |
requestAction(action, payload?) |
返回宿主动作结果的 Promise |
reportError(error) |
向宿主报告主题错误 |
dispose() |
释放监听和待处理请求 |
数据字段与缺失值
snapshot.telemetry[key] 是 RideUiMetricValueV1:
| 字段 | 使用方法 |
|---|---|
value / canonicalUnit |
数值与计算单位;null 表示不可用 |
displayValue / displayUnit |
宿主格式化文本和展示单位 |
source |
gps、bms、controller、vehicle、fused 或 none |
quality |
measured、fused、held、estimated 或 missing |
freshness |
fresh、stale 或 unavailable |
sampledAtEpochMs |
样本墙上时钟时间,可能为 null |
ageMs / timeMappingQuality |
可选的新鲜度和时间映射信息 |
sourceRef 等来源元数据 |
不透明标识,不解释为设备地址或可调用会话 |
estimateMeta |
可选估算语义、状态和覆盖信息 |
普通文本优先用展示字段,图形计算用数值。null 不能补成 0,过期或估算值不能冒充实时测量。常见键包括 speed、soc、power、busCurrent,其他字段按契约读取;每个设备只会提供它实际支持的子集。
挡位与 P 状态(API 1.11)
这两个状态通过 subscribeSnapshot 接收,不属于高频快帧。它们没有单位,且相互独立:车辆处于 P 时仍可以选定低/中/高挡。
| 键 | 数值含义 |
|---|---|
vehicleGear |
1=低挡、2=中挡、3=高挡;未知或缺失为 null |
vehicleParking |
1=处于 P、0=解除 P;未知或缺失为 null |
极核/ZEEHO 已提供这两个状态。九号 MMAX90 的实时挡位和 P 映射尚未验证,返回 null、quality: 'missing'、freshness: 'unavailable';零车速不能用来推断 P。旧 API 1.x 宿主缺少新字段时,SDK 同样补齐为不可用。
client.subscribeSnapshot(snapshot => {
const gear = snapshot.telemetry.vehicleGear
const parking = snapshot.telemetry.vehicleParking
const gearText = gear?.freshness === 'fresh' && gear.value != null
? ({ 1: '低挡', 2: '中挡', 3: '高挡' } as Record<number, string>)[gear.value] ?? '--'
: '--'
const parkingText = parking?.freshness === 'fresh' && parking.value != null
? parking.value === 1 ? 'P' : '已解除 P'
: '--'
console.log(gearText, parkingText)
})
不要用真值判断过滤 0。字段保留原始来源和采样时间;电池更新不会使旧状态重新变成 fresh。陈旧状态可以用于历史提示,但不能当作当前状态。预览器的 Vehicle gear / parking states 场景依次展示六种组合、未知挡位、陈旧与不可用状态,也支持手动调整。
速度显示帧
收到 subscribeDisplayFrame 回调后,速度数字、指针和进度条使用 frame.speedKmh,包括 null。显示值为空时不要回退到 telemetry.speed。frame.state 为 live、held 或 missing。
telemetry.speed 保持测量语义。不要在主题中叠加第二次平滑。速度小数可用 resolveRideUiSpeedPrecision(context.speedDecimalEnabled, hideSpeedDecimal) 计算。显示帧中的序号和单调时间可用于动画顺序,不要仅靠墙上时钟判断先后。
能力和动作
context.capabilities 决定当前允许请求的动作,context.environment?.dataCapabilities 描述数据能力。清单的 requiredCapabilities / optionalCapabilities 是声明,不是授权。
| 动作 | 意图 |
|---|---|
ride.request-exit / ride.refresh |
请求退出或刷新 |
display.set-orientation |
请求方向,payload 为 { mode: 'portrait' } 或 { mode: 'landscape' } |
theme.open-picker / theme.open-settings |
打开宿主主题选择或设置 |
theme.config-patch |
提交版本化主题设置,见设置指南 |
vehicle.open-settings |
请求宿主打开设置界面,不授予车辆参数写入权 |
dynamics.recalibrate / ride.black-screen-lock |
请求宿主处理校准或锁屏 |
feedback.haptic / preview.metrics-reorder |
宿主声明支持时请求触感或预览排列 |
列表描述动作名称,不代表所有宿主、所有模式均可用。除有明确 payload 示例的动作外,参数以公共类型和宿主支持范围为准,不自行猜测。
动作结果含 requestId、ok、可选 result 和 error。失败码包括 denied、unavailable、invalid、conflict、timeout、failed。失败后保持 UI 与宿主实际状态一致,不显示虚假的成功状态。
兼容性
清单声明 API 主版本和最低次版本。API 1.x 内容忍未知可选字段,访问可选 environment 时使用空值保护。新功能先检查能力。SDK 包版本不能代替宿主实际 API 和能力判断。
更多设置流程见 主题清单与设置,运行规则见 构建与 App 安装。