预警表达式教程
基础语法
字面值
数据类型 | 字面值 |
---|---|
Comment | /* */ or // |
Boolean | true 、false |
Integer | 42 、0x2A 、0o52 、0b101010 |
Float | 0.5 、.5 |
String | "foo" 、'bar' |
Array | [1, 2, 3] |
Map | {a: 1, b: 2, c: 3} |
Nil | nil |
操作符
操作符 | 描述 |
---|---|
Arithmetic | + , - , * , / , % (modulus), ^ or ** (exponent), |
Comparison | == , != , < , > , <= , >= |
Logical | not or ! , and or && , or or || |
Conditional | ?: (ternary), ?? (nil coalescing) |
Membership | [] , . , ?. , in |
String | + (concatenation), contains , startsWith , endsWith |
Regex | matches |
Range | .. |
Slice | [:] |
Pipe | | |
上面介绍了基础语法和标识,更多资源可以查看:https://expr-lang.org/docs/language-definition (opens in a new tab)。Expr 表达式语法和 C、Go、Lua、Python,JavaScript 高度相似,可以举一反三。
数据示例
以下是一个气象站数据的 JSON 示例。这个示例包含了气象站的基本信息、位置、以及一系列的气象观测数据:
{
"observation": {
"timestamp": "2024-12-06T15:30:00Z",
"weather": {
"temperature": {
"value": 5.0,
"unit": "C"
},
"humidity": {
"value": 85,
"unit": "%"
},
"pressure": {
"value": 1012.3,
"unit": "hPa"
},
"wind": {
"speed": {
"value": 12.0,
"unit": "km/h"
},
"direction": {
"value": 270,
"unit": "degrees"
}
}
}
}
}
在这个 JSON 示例中:
observation
对象包含了气象观测数据,包括观测的时间戳。weather
对象包含了具体的气象数据,如温度、湿度、气压、风速、风向、降水量、云量和能见度。- 每个气象数据项都包含了
value
和unit
字段,分别表示观测值和单位。
这个 JSON 结构是通用的,可以根据实际需要添加或删除字段。
示例1:气象站数据处理
温度大于 30:
observation.weather.temperature.value > 30
气压在某个阈值:
observation.weather.pressure.value > 1001 && observation.pressure.value < 1005
温度*湿度在某个阈值区间:
observation.weather.temperature.value * observation.weather.humidity.value > 30
示例2:温湿度传感器数据处理
下面是 Modbus 采集上来的数据,要求:当值 >100 的时候预警:
{
"tag": "temp2",
"alias": "传感器1-温度",
"slaverId": 2,
"lastFetchTime": 1733836405282,
"value": "222.2000"
}
预警规则:
float(value) > 100
这里涉及到一个类型转换 float(value),"222.2000" 是个字符串,使用类型转换即可直接转换为对应的类型。
示例3:高级操作
有两个温湿度传感器,点位定义如下:
现在采集两个 Modbus 传感器的数据,采集到的数据如下:
{
"data": [
{
"tag": "humi1",
"alias": "传感器1-湿度",
"slaverId": 1,
"lastFetchTime": 1733891948921,
"value": "1111.1000"
},
{
"tag": "temp1",
"alias": "传感器1-温度",
"slaverId": 1,
"lastFetchTime": 1733891949048,
"value": "1111.1000"
},
{
"tag": "humi2",
"alias": "传感器2-湿度",
"slaverId": 2,
"lastFetchTime": 1733891949176,
"value": "1111.1000"
},
{
"tag": "temp2",
"alias": "传感器2-温度",
"slaverId": 2,
"lastFetchTime": 1733891949303,
"value": "1000.0000"
}
]
}
规则:
- 传感器1-温度是否高于 1000 摄氏度?
any(data, {.tag == "temp1" && float(.value) >= 1000})
- 传感器2-湿度是否高于 80?
any(data, {.tag == "humi2" && float(.value) >= 80})
- 传感器 1、传感器 2 的温度是否都高于 1000?
any(data, {
.tag == "temp1" &&
float(.value) >= 1000 &&
.tag == "temp2" &&
float(.value) >= 1000
}
)
- 传感器 1、传感器 2 的温度和是否大于 2000?
sum(data | filter(.tag == "temp1" || .tag == "temp2") | map(float(.value)))
解释:"|" 是管道操作符,表示将上一个的操作结果作为输入进入下一个流程。filter 是过滤器,可以根据条件来过滤数据。map 是筛选器,用于删选某个字段。
下面是过滤器 filter 的使用示例:
data | filter(.tag == "temp1" || .tag == "temp2")
[
{
"alias": "传感器1-温度",
"lastFetchTime": 1733891949048,
"slaverId": 1,
"tag": "temp1",
"value": "1111.1000"
},
{
"alias": "传感器1-温度",
"lastFetchTime": 1733891949303,
"slaverId": 2,
"tag": "temp2",
"value": "1000.0000"
}
]
map 操作是为了返回新的 value 列表:
(data | filter(.tag == "temp1" || .tag == "temp2") | map(float(.value)))
返回:
[
1111.1,
1000
]
sum 则是求和:
sum(data | filter(.tag == "temp1" || .tag == "temp2") | map(float(.value)))
总结
用户可以根据上述教程初步入门规则表达式。
上述三个示例已经足以入门,如果想了解高级用法请看更详细的教程:https://expr-lang.org/docs/language-definition, (opens in a new tab) 或者使用 expr playground 调试模拟:https://expr-lang.org/playground (opens in a new tab)