仪表数据

通过 $data 读取当前驾驶数据和历史采样,并将结果用于文字、图形和曲线。本文说明数据配置、读数结构、OBD 参数及更新规则。

数据接口

仪表通过 $data 使用已定义的输入。$data.current 提供当前输入,$data.history 提供当前行程最近 30 秒的采样序列。字段名称来自本仪表的输入标识符;例如,把基础速度输入命名为 speed,通过 $data.current.speed 读取;把 OBD 输入命名为 coolant,通过 $data.current.coolant 读取。

速度、距离、时间和 OBD 等量值包含 value 与 unit。例如 { value: 42.3, unit: 'km/h' } 包含数值与单位;位置、G 值等字段提供各自分量。数值、文本、开关与选择项则直接返回数字、字符串或布尔值,不再包一层 value。完整规则见 $data API。

定义输入与本机绑定

点击编辑器顶部的仪表名称,打开 仪表设置 → 输入绑定。齿轮进入 参数配置,用于定义输入的名称、标识符和类型;返回输入绑定后填写本机数值,或为 OBD 输入选择自己的车辆参数。基础数据由 App 自动提供。

类型 配置与脚本读到的内容
数值 设置默认值及可选上下限;脚本直接读到数字,例如 $data.current.limit。
文本 设置默认文字;脚本直接读到字符串,例如 $data.current.label。
开关 设置默认开关状态;脚本直接读到布尔值,例如 $data.current.showUnit。
选择项 定义可选文字和默认项;脚本读到选中的字符串,例如 $data.current.style。
基础数据 选择速度、G 值、位置或时间等来源;读数结构随来源而定。
OBD 数据 定义预期值类型,再在输入绑定中选择设备及车辆参数;读数为 { value, unit } 或 null。

输入标识符为 1–100 个英文字母和数字,以字母开头,同一仪表内不得重复;每块仪表最多 256 项输入。名称用于界面显示,标识符用于代码。修改显示名称不改变访问路径,修改标识符则需要同步修改代码。

例如,用 coolant 表示冷却液温度后,绑定不同设备的相应参数,代码仍读取 $data.current.coolant。编辑器按输入定义提供表达式与类型提示。数值默认值必须落在上下限内,选择项必须有互不重复的非空选项及有效默认项;保存提示错误时先修正对应字段。

当前读数

新建仪表已包含标识符为 speed、来源为 速度 的基础数据输入;已有作品可在 参数配置 中检查该定义。在 main() 中取得 $data.current.speed,即可使用本次速度的数值和单位。下例将数值四舍五入后显示在上方,单位显示在下方;没有可用速度时显示 —。

配置正确的基础速度输入始终保留对象,缺测时 value 为 null,unit 仍为设置中的 km/h 或 mph。== null 检查数值是否缺测,速度为零时仍显示 0。字段名由输入标识符决定;若改为 vehicleSpeed,代码也应改为 $data.current.vehicleSpeed。

function main() {
  const speed = $data.current.speed;
  return (
    <VStack spacing={8}>
      <Text fontSize={64} color={$env.foreground}>
        {speed?.value == null ? '—' : Math.round(speed.value)}
      </Text>
      <Text fontSize={16} color={$env.accent}>
        {speed?.unit ?? $env.speedUnit}
      </Text>
    </VStack>
  );
}

OBD 参数

先连接 OBD 设备并确认目标参数能产生有效读数。进入 参数配置 添加 OBD 数据 输入,例如名称为“冷却液温度”、标识符为 coolant,预期类型选择数值。返回 输入绑定,为它选择设备下的冷却液温度参数。下面的示例通过 $data.current.coolant 读取,不使用车辆参数 UUID 作为脚本字段名。

已绑定且配置存在的读数始终包含 value 和 unit。设备未连接、读数过期或查询失败时,value 为 null,unit 仍取所选设备保存的参数配置;无单位参数使用 unit: null。未绑定或设备、参数配置已不存在时,整个输入为 null。

value 可以是数字或文本映射后的字符串。预期类型用于编辑提示;绑定可能返回不同类型的参数时会提示,但仍可绑定,实际值不会因此强制转换。数字格式化前应检查类型。更换适配器或导入他人作品后,重新绑定相应输入即可沿用原代码。

function main() {
  const reading = $data.current.coolant;
  const value = reading?.value;
  const text =
    value == null
      ? '—'
      : typeof value === 'number'
        ? value.toFixed(1)
        : value.toString();
  return (
    <VStack spacing={8}>
      <Text fontSize={48} color={$env.foreground}>
        {text}
      </Text>
      <Text fontSize={16} color={$env.accent}>
        {reading?.unit ?? ''}
      </Text>
    </VStack>
  );
}

更新与历史采样

自定义仪表没有统一固定的刷新频率。当前输入、输入定义或显示环境变化时,CapDrive 会重新执行脚本并调用 main();完全相同的输入会跳过。脚本串行执行,处理中只保留最新的待处理输入。动画由绘制端独立执行,不需要逐帧运行脚本,也不会提高传感器或 OBD 的采样频率。

App 统一维护当前行程最近 30 秒的已采集数据,最多按 5 Hz 采样、保留 151 项。打开仪表可读取已有窗口;暂停绘制或重建运行实例不丢失窗口,行程结束、切换行程或运行模式时重置。历史增长或过期清理不会单独触发脚本;希望曲线随时间推进时,可定义一个标识符为 elapsed、来源为已记录时长的基础输入。

定义了 speed 和 elapsed 输入后,可用每个历史采样的 elapsed.value 作横坐标、speed.value 作纵坐标;时间戳使用毫秒,已记录时长使用秒。保留缺测区间,不用后来的 OBD 值回填历史。预览使用模拟输入,仪表盘使用实际数据。

数据有效性

null 表示当前没有可用读数,0 是有效数值。保留这两种状态,仪表才能如实显示停车、连接中断或暂时缺测。可用 value == null ? '—' : value 处理数值,避免通过 value || 0 将所有缺测显示为零。

文本映射可能产生空字符串,也可能在未匹配时返回数字或 null,具体行为由参数配置决定。接收文字的 View 可以显示字符串;参与计算和数字格式化的值应先检查类型。

排查缺测时,按字段对应的数据源检查:基础速度查看定位状态;OBD 参数查看当前设备、测试读取结果和参数配置。数据源正常后,再核对仪表选择的字段与代码表达式。

接下来