跳转至

属性模型与读写

最后更新:

车辆属性源被转换为同一套公开模型,但来源差异不会被抹掉。source + canonicalId + areaId 共同确定一个属性实例。

属性选择器

EvccPropertySelector 至少提供 ID 或精确名称之一:

EvccPropertySelector(
    id = 557849089L,             // 可改为 name = "车速"
    source = Source.AUTO,        // 也可显式指定来源
    areaId = null,
    resolutionMode = ResolutionMode.AUTO_PRIORITY,
)

AUTO 来源规则

未指定来源时按下列固定顺序解析:

  1. ECARX_VHAL(只在精确适配的 L946 上可用)
  2. VHAL
  3. APVP
  4. VEHICLE_AIDL
  5. CAPI
  6. ADAPT_API
  7. SOA
  8. GEELY_CAPI
  9. GEELY_AIDL

只检查用户当前已经启用的来源。AUTO_PRIORITY 选择第一个匹配项,结果通过 resolvedSource 返回实际来源,并可在 candidates 中提供候选项。STRICT_UNIQUE 要求唯一匹配, ALL_MATCHES 用于目录/解析工具查看全部候选。

名称查询默认采用精确匹配。需要发现名称时先用目录搜索,不要把模糊搜索结果直接用于写入。

ECARX_VHAL 的目录直接来自目标系统 HIDL VHAL 的 VehiclePropConfig。每个 area 独立建项,读取和订阅使用原生类型与区域;写入只允许原生配置标记可写的属性,并在单次下发后读回确认。它不使用 EAS 固定 area、CAPI 权限代理或属性名推测来冒充有效能力。

区域规则

  • 调用方传入 areaId 时只匹配该区域。
  • 未传区域时优先区域 0。
  • 没有区域 0 且只有一个候选区域时,选择该区域。
  • 同时存在多个非零区域时返回 AMBIGUOUS_AREA 和候选项,调用方必须明确选择。

规范属性描述

EvccPropertyDescriptor 对齐 EVCC 属性表格中可以稳定公开的信息:

字段 含义
source 实际属性源
canonicalId / nativeId / aliases EVCC 规范 ID、来源原生 ID、别名
hexId / name / description 展示 ID、名称和按可靠优先级补齐的说明
group 属性分组
areaType / areaId / areaName 区域定义
dataType / access / changeMode 类型、读写能力和变化模式
enumOptions 来源确实定义的枚举选项
userNote 可选用户备注,不是车辆协议权威元数据
sourceGeneration 来源连接代次,用于判断缓存是否跨重连失效

属性源直接提供的说明和动态枚举始终优先;来源没有说明时,EVCC 只会使用按真实属性名或 “ID + 真实属性名”精确匹配的车型元数据补齐 description 与 enumOptions。占位名称、纯 ID 旧映射和跨车型猜测不会命中。userNote 只返回用户在属性诊断页明确保存的本地备注,不会把 APVP 等来源的协议结构信息冒充为用户备注。仍为空的字段表示没有可靠定义,不表示 false。

类型化值

EvccValue 同时提供类型化字段、rawValue 和 displayValue。根据 type 读取对应字段,不能只 解析显示字符串。initialized 与 status 用来区分尚未获得值、来源不可用和真实空字符串。

when (value.type) {
    ValueType.LONG -> value.longValue
    ValueType.DOUBLE -> value.doubleValue
    ValueType.BOOLEAN -> value.booleanValue
    ValueType.STRING -> value.stringValue
    ValueType.JSON -> value.stringValue
    ValueType.BYTES_BASE64 -> value.stringValue
    else -> null
}

写入

写入必须携带选择器和 EvccValue。建议先使用 validateOnly = true 做预检查,再经用户操作确认 执行真实写入。

val result = client.writeProperty(
    EvccWriteRequest(
        requestId = UUID.randomUUID().toString(),
        selector = EvccPropertySelector(id = 123L),
        value = EvccValue.ofBoolean(true),
        validateOnly = true,
    )
)

AUTO 写入一旦选中来源,就只对该来源尝试一次。即使写入失败,也不会向低优先级来源继续写, 避免同 ID 在另一个协议中代表不同控制项。批量写入最多 100 项,保持请求顺序、逐项返回且不是事务。

普通目录

queryPropertyDirectory(EvccPageRequest) 使用 DIRECTORY 时只读取已启用来源的可发现描述符, 只利用当前已有的来源适配器/缓存,不会为了普通目录主动连接尚未连接的来源,也不会进入 APVP 全量 模式。因此普通目录可能少于实时全量扫描,但固定成本更低。第一页返回 snapshotToken;后续页必须 同时回传该令牌和 pageToken,并保持来源、查询词、模式和 includeValues 不变。目录快照约保留 60 秒,过期后从第一页重新查询。limit 最大 500;只有同时拥有 property.read 时才能设置 includeValues = true。

目录页还受 Binder 大小预算约束:即使请求了 500 项,服务也可能提前截断当前页并给出新的 nextPageToken。客户端必须以服务返回的令牌为准,不能用“本页数量小于 limit”判断已经结束。 单个不可变目录快照最多 50,000 条,估算内存不超过 16 MiB;所有应用当前保留的目录快照合计最多 50,000 条和 32 MiB。达到预算时旧快照可能提前被回收,或新请求返回 PAYLOAD_TOO_LARGE,此时应按 来源或关键词缩小目录范围并从第一页重新查询。