跳转至

EVCC 公式与变量系统参考手册

最后更新:

EVCC 内置了一套完整的表达式计算引擎,可在控制台卡片、悬浮窗、状态栏信息卡、自动化规则等多个场景中使用。本文档详细说明所有支持的语法、函数和使用方式。

按 EVCC v2.9.61 源码核对,更新日期:2026-08-17。本手册同时包含快速上手和完整参考;Lua 中读取同一套变量的方法见《EVCC Lua 脚本手册》。


快速上手

先记住下面五种写法,就能完成大多数配置:

x * 0.1                              控制台/悬浮窗中转换当前属性值
$speed * 3.6                         读取自定义变量并计算
$prop(557849089)                     读取另一个车辆属性
clamp($current + $ble_rotation, 0, 100)
                                     用 BLE 旋钮在 0~100 内调节当前值
温度: {round(x * 0.1)}°C              在文字中嵌入计算结果

基本规则:

  • x 只在控制台、悬浮窗、状态栏信息卡等有“当前属性”的显示表达式中有值;
  • $name 或 ${name} 读取 EVCC 变量,$prop(十进制属性ID) 读取车辆属性;
  • 数字可以直接使用 + - * / % ^、括号和函数;
  • 固定文字放进表达式时要加英文引号,普通文字中嵌入计算请使用 {...};
  • 变量不存在、属性未读到或公式解析失败时,不要假定结果会自动变成 0。

目录


1. 在哪里可以使用公式

使用位置 字段名 变量 x $prop / $变量 公式计算 pad()
控制台卡片 (INFO) 运算公式 ✅ 当前属性值 ✅ ✅ ✅
悬浮窗信息项 转换表达式 ✅ 当前属性值 ✅ ✅ ✅
状态栏信息卡 转换表达式 ✅ 当前属性值 ✅ ✅ ✅
EVCC mini 仪表页 属性运算公式 ✅ 当前属性值 ✅ ✅ ✅
自动化 — 变量值 值字段 ❌ ✅ ✅ ✅
自动化 — 动作值 值/命令字段 ❌ ✅ ✅ ✅
自动化 — BLE 数据 Payload 字段 ❌ ✅ ✅ ✅
模板块 {表达式} 任意文本 ✅ (需传入) ✅ ✅ ✅
控制台卡片 (时间) 运算公式 ❌ ❌ ❌ ❌ (此处为日期格式)

x 变量:在控制台/悬浮窗/状态栏的运算公式中,x 自动绑定为该卡片监听的车辆属性的当前数值。 统一语法:除时间卡片外,控制台、悬浮窗、状态栏、EVCC mini、自动化变量值和动作参数都使用同一套表达式语法。


2. 变量引用

语法 含义 示例
$变量名 引用全局变量的值 $speed * 3.6
${变量名} 同上,花括号避免歧义 ${voltage}V
$prop(属性ID) 读取车辆属性实时值 $prop(289410048)
$prop(属性ID, 区域ID) 指定区域读取 $prop(289410048, 1)
$prop(属性ID, 区域ID)[下标] 读取数组或结构体 Data 中的指定项;省略区域时默认为 0 $prop(577765445)[2]

数组下标从 0 开始,所以 [2] 是第三项。支持裸逗号数组、[...] 数组和 Data=[...] 结构体显示值;取出的值仍可继续参与公式计算。越界、空值或存在多个无法确定的数组字段时视为无有效值,不会以 0 代替。

$prop(...) 中的属性 ID、区域 ID 目前只接受十进制整数。属性页面里看到的 0x... 十六进制 ID 需要先换算为十进制后再填写;数组下标虽然可以被语法识别为负数,但负下标没有有效值。

变量替换在公式求值之前执行。替换后如果结果是一个数学表达式,会自动进入公式引擎计算。


3. 算术运算符

运算符 含义 示例 结果
+ 加法 5 + 3 8
- 减法 10 - 4 6
* 乘法 6 * 7 42
/ 除法 22 / 7 3.142857
% 取模 (余数) 10 % 3 1
^ 幂运算 (右结合) 2 ^ 10 1024
() 括号 (最高优先级) (2 + 3) * 4 20

4. 比较运算符

比较运算符返回 1(真)或 0(假),主要配合 if() 使用。

运算符 含义 示例 结果
> 大于 x > 100 1 或 0
< 小于 x < 0 1 或 0
>= 大于等于 x >= 60 1 或 0
<= 小于等于 x <= 255 1 或 0
== 等于 x == 0 1 或 0
!= 不等于 x != 1 1 或 0

5. 函数列表

5.1 取整与数值

函数 参数 作用 示例
round(x) 1 按 floor(x + 0.5) 取最近整数 round(3.7) → 4
floor(x) 1 向下取整 (向负无穷) floor(-3.2) → -4
ceil(x) 1 向上取整 (向正无穷) ceil(3.1) → 4
trunc(x) 1 向零截断 trunc(-3.7) → -3
abs(x) 1 绝对值 abs(-5) → 5
sign(x) 1 符号函数,返回 -1 / 0 / 1 sign(-42) → -1
frac(x) 1 小数部分 frac(3.75) → 0.75
min(a, b) 2 取较小值 min(x, 100)
max(a, b) 2 取较大值 max(x, 0)
clamp(x, lo, hi) 3 限定范围 clamp(x, 0, 255)

trunc 与 floor 的区别:正数时行为相同,负数时 trunc(-3.7) = -3,floor(-3.7) = -4。

负数取整提示:当前 round() 按 floor(x + 0.5) 实现,因此 round(-1.5) 的结果是 -1,并不是远离 0 的 -2。frac(x) 按 x - floor(x) 计算,所以 frac(-3.2) 为 0.8。

5.2 幂与对数

函数 参数 作用 示例
sqrt(x) 1 平方根 sqrt(16) → 4
pow(x, y) 2 x 的 y 次方 pow(2, 10) → 1024
hypot(a, b) 2 斜边长度 √(a²+b²) hypot(3, 4) → 5
log(x) 1 常用对数 (以10为底) log(100) → 2
ln(x) 1 自然对数 (以e为底) ln(2.718) ≈ 1

5.3 三角函数

所有三角函数使用弧度制。可用 rad() / deg() 进行角度与弧度的转换。

函数 参数 作用
sin(x) 1 正弦
cos(x) 1 余弦
tan(x) 1 正切
asin(x) 1 反正弦,返回弧度
acos(x) 1 反余弦,返回弧度
atan(x) 1 反正切,返回弧度
atan2(y, x) 2 二参数反正切,返回弧度
rad(度) 1 角度转弧度
deg(弧度) 1 弧度转角度

示例:sin(rad(45)) ≈ 0.707

5.4 条件与逻辑

函数 参数 作用 示例
if(条件, 真值, 假值) 3 条件不为0取真值,否则取假值 if(x > 100, 100, x)
and(a, b) 2 逻辑与,两个非零返回1 and(x > 0, x < 100)
or(a, b) 2 逻辑或,任一非零返回1 or(x == 1, x == 3)
not(a) 1 逻辑非,零返回1,非零返回0 not(x == 0)
concat(a, b, ...) 多个 拼接文本 concat("电量 ", x, "%")

复合条件示例:

if(and(x >= 0, x <= 100), x, 0)
当 x 在 0~100 范围内时返回 x,否则返回 0。

if(or(x < -40, x > 215), -999, x)
超出温度范围时返回 -999 (错误标记)。

5.5 比较函数

这些函数与比较运算符(>、< 等)功能相同,在模板块 {...} 中有时更方便使用。

函数 等价运算符 返回值
eq(a, b) a == b 1 或 0
neq(a, b) a != b 1 或 0
gt(a, b) a > b 1 或 0
lt(a, b) a < b 1 或 0
gte(a, b) a >= b 1 或 0
lte(a, b) a <= b 1 或 0

5.6 位运算

操作数会先被截断为整数 (Long) 再进行位运算,结果转回浮点数返回。这在处理 VHAL 属性的位域标志位时非常实用。

函数 参数 作用 示例
band(a, b) 2 按位与 (AND) band(x, 255) 取低8位
bor(a, b) 2 按位或 (OR) bor(x, 4) 设置bit2
bxor(a, b) 2 按位异或 (XOR) bxor(x, 255) 翻转低8位
bnot(a) 1 按位取反 (NOT) bnot(0) → -1
shl(a, n) 2 左移 n 位 shl(1, 3) → 8
shr(a, n) 2 右移 n 位 shr(255, 4) → 15
bit(x, n) 2 取第 n 位 (0或1) bit(x, 3) 取bit3

常见用法:

bit(x, 0)       → 取最低位 (奇偶判断)
band(x, 255)    → 取低 8 位字节
shr(x, 8)       → 取高位字节 (16位值)
band(shr(x, 4), 15)  → 取 bit4~bit7 (高半字节)

5.7 映射与插值

函数 参数 作用 示例
map(x, 输入最小, 输入最大, 输出最小, 输出最大) 5 线性映射 map(x, 0, 4095, 0, 100)
lerp(a, b, t) 3 线性插值 a+(b-a)*t lerp(0, 100, 0.3) → 30

map 详解:将输入值从一个范围线性映射到另一个范围。

map(x, 0, 255, -40, 215)    → 字节值映射为温度 (℃)
map(x, 0, 4095, 0, 100)     → 12位ADC值映射为百分比
map(x, 0, 1023, 0, 5)       → 10位ADC值映射为电压 (V)

5.8 格式化指令

指令 参数 作用 示例
pad(表达式, 位数) 2 前导补零 + 溢出保护 pad(x, 4)

pad 不是普通的数学函数,而是格式化指令。它的行为:

  1. 计算内层表达式的值
  2. 截断为整数
  3. 限制在 0 ~ 10^位数 - 1 范围内 (溢出保护)
  4. 以前导零填充到指定位数
表达式 x = 42 x = 1234 x = 99999
pad(x, 4) 0042 1234 9999
pad(x, 6) 000042 001234 099999
pad(x * 0.1, 3) 004 123 999

嵌套使用:

pad(clamp(x, 0, 9999), 4)     → 先限制范围再补零
pad(band(x, 255), 3)          → 取低8位后补零为3位

6. 内置变量

以下变量无需创建,可直接在公式中使用 $变量名 引用。

变量名 值 示例
$time 当前时间 HH:mm:ss 14:30:25
$date 当前日期 yyyy-MM-dd 2025-03-23
$datetime 日期+时间 2025-03-23 14:30:25
$timestamp Unix 时间戳 (毫秒) 1711186225000
$hour 当前小时 (00-23) 14
$minute 当前分钟 (00-59) 30
$bpm 当前音乐 BPM;无音乐、尚未匹配或匹配失败时为 0 128
$music_state 当前音乐状态:playing / paused_or_stopped / none playing
$gps_available 是否有最近定位缓存,1 有、0 无 1
$gps_lat / $latitude 最近定位纬度 30.123456
$gps_lng / $gps_lon / $gps_long / $longitude 最近定位经度 120.123456
$gps_altitude 海拔(米,无海拔时为空) 12.3
$gps_accuracy 定位精度(米,无精度时为空) 8
$gps_speed 定位速度(米/秒,无速度时为空) 0
$gps_bearing 定位方向角(度,无方向时为空) 180
$gps_provider 定位来源 gps
$gps_time 定位时间戳 (毫秒) 1711186225000
$gps_age_ms 定位缓存距离当前的毫秒数 2500

GPS 变量读取系统最近一次定位缓存,不主动发起定位;如果车机暂时没有定位,$gps_available 返回 0,其他 GPS 值返回空字符串。

音乐变量来自 EVCC 当前音乐转发状态:暂停时 $bpm 会保留当前歌曲已识别到的数值;切歌后尚未匹配、匹配失败,或当前没有音乐会话时返回 0。$bpm 和 $music_state 是只读变量,不能被自动化“设置变量”动作或 Lua var.write() 覆盖。

表达式的比较运算是数值比较,因此可以直接写 $bpm >= 120,但不要在数学表达式里写 $music_state == "playing"。音乐状态请在自动化的“变量比较”中比较字符串,或在 Lua 中用 var.read("music_state") 判断。

上下文变量(仅在特定动作/触发中可用):

变量名 可用场景 含义
$current SET_PROPERTY 动作 当前属性的实时值
$ble_button BLE 按键触发 触发的按键编号 (1-14)
$ble_rotation BLE 旋钮触发 旋转值: ±1 (不等待角度) 或实际角度

7. 模板块语法

字符串表达式

表达式可以输出文字,但固定文字必须用英文单引号或双引号包起来。只要 + 的任一边是字符串,+ 就表示拼接文本。

"电量 " + x + "%"                         → x=80 时输出:电量 80%
if($a > 0, "东经 " + $a, "西经 " + abs($a)) → $a=-3 时输出:西经 3
concat("温度 ", round(x * 0.1), "°C")      → 拼接多个文本/数字片段

不要把文字裸写在 if() 分支里:

if($a > 0, 东经$a, 西经abs($a))             → 错误:东经/西经没有加引号

如果整段是普通文字、ADB 命令、包名、日期等,EVCC 会原样保留,不会强行按公式解析。

模板块

在自动化变量值中,可以用 {表达式} 在文本中嵌入计算结果,大括号外的文本原样保留。

温度: {x * 0.1}°C
时间: {$gps_time * 0.001}秒

如果 x = 234,输出:温度: 23.4°C

注意:${变量名} 是变量引用(前面有 $),{表达式} 是模板块(前面没有 $),两者不会冲突。

如果写成 时间: $gps_time*0.001秒,EVCC 只会先替换 $gps_time,不会在混合文本中单独计算后面的 *0.001。这类“文字 + 公式 + 单位”的场景请使用模板块。


8. 运算符优先级

从高到低:

  1. () 括号、函数调用
  2. ^ 幂运算 (右结合: 2^3^2 = 2^(3^2) = 512)
  3. * / % 乘法、除法、取模
  4. + - 加法、减法
  5. > < >= <= == != 比较 (最低)

示例:x + 1 > y * 2 等价于 (x + 1) > (y * 2)


9. 实用示例

数值转换

x * 0.1                          → 原始值缩放 (如 1234 → 123.4)
(x - 32) * 5 / 9                 → 华氏度转摄氏度
x / 3.6                          → km/h 转 m/s
map(x, 0, 255, -40, 215)         → 字节值映射为温度

条件显示

if(x > 100, 100, x)              → 超过100封顶为100
if(x == 0, -1, 1000 / x)         → 避免除零
if(and(x >= 18, x <= 65), 1, 0)  → 判断是否在范围内

VHAL 位域提取

bit(x, 0)                        → 提取最低位 (开关状态)
bit(x, 3)                        → 提取第3位
band(x, 255)                     → 取低8位
band(shr(x, 8), 255)             → 取第2个字节
if(bit(x, 5) == 1, 1, 0)         → 检查bit5是否置位

格式化输出

pad(x, 4)                        → 补零为4位: 42 → "0042"
pad(clamp(x, 0, 9999), 4)        → 限制范围 + 补零
pad(band(x, 255), 3)             → 取低8位 + 补零为3位

跨属性引用

$prop(289410048) * 0.1            → 引用其他属性并缩放
x + $prop(289410049)              → 当前属性值 + 另一属性值
hypot(x, $prop(289410049))        → 两个属性的向量合成

自动化变量计算

$speed * 3.6                      → m/s 转 km/h
clamp($current + $ble_rotation, 0, 100)  → 旋钮增减值 (限 0~100)
round($prop(123) / 216 / 10) * 10       → 四舍五入到十位
if($hour >= 22, 1, if($hour < 6, 1, 0)) → 判断是否深夜
if($a > 0, "东经 " + $a, "西经 " + abs($a)) → 按正负值输出方向文字
$bpm * 2                         → 读取音乐 BPM 参与计算;无音乐时结果为 0

音乐变量联动

自动化里可直接选择“变量比较”触发器或条件:

变量名:bpm
比较方式:大于
目标值:120
变量名:music_state
比较方式:等于
目标值:playing

也可以选择“变量变化”触发器监听歌曲 BPM 或播放状态的变化。music_state 是文本值,不适合放进数值公式中比较。


10. 注意事项

Hex 数据不会被误处理

BLE 广播等场景的 hex 数据(如 AA BB 01 02)不会被公式引擎误处理。系统有三层保护: - 纯 hex 数据不含数学运算符和函数调用括号,会被直接放行 - 所有函数名都包含非 hex 字符(G-Z),不会与 hex 数据子串匹配 - 即使意外进入解析器,解析失败会返回原始字符串

数据类型

  • 所有计算使用 64 位浮点数(Double)。位运算时操作数先截断为 Long
  • 比较运算和逻辑函数返回 1.0(真)或 0.0(假)
  • 固定文字必须加引号;pad()、concat() 和字符串分支的 if() 会返回文本
  • 除字符串拼接和字符串分支外,算术、比较和数学函数都要求输入可转为数值;无法解析的文本不会被偷偷当成 0

解析失败与空值

  • $prop(...) 没有读到值、数组越界或变量不存在时,原引用会保持未解析状态,不会自动替换成 0
  • 在变量替换场景中,表达式解析失败时会尽量保留原始文本,避免把包名、命令或普通说明误算成公式
  • 显示表达式无法得到有效结果时,卡片会按所在组件的兜底逻辑处理;不要依赖“错误公式等于 0”

valueMap 与 displayExpression 的优先级

在控制台卡片和悬浮窗中: - 如果设置了 valueMap(值映射表),则优先使用映射,不执行公式 - 如果没有 valueMap 且设置了 displayExpression(运算公式),才执行公式 - decimalPlaces(小数位数)在公式结果后应用(pad() 会跳过此步)

跨属性依赖

在控制台运算公式中使用 $prop(id) 引用其他属性时,系统会自动建立依赖关系:当被引用的属性值变化时,使用它的卡片也会自动刷新。

时间数据源

时间类型的卡片,"运算公式"字段的含义不同——它是 Java SimpleDateFormat 时间格式,如 HH:mm、yyyy/MM/dd HH:mm:ss,不是数学表达式。

Geely 属性公式

$prop(geely_aidl:signal:0x4061,1) 和 $prop(geely_capi:sensor:0x100100,0) 使用来源、通道、原始 ID、请求区域定位属性。缺失或关闭的来源保持引用未解析,不替换为 0,不转向其他来源。包含 Geely 引用的自动化规则由应用执行。