预警表达式教程
基础语法
字面值
| 数据类型 | 字面值 | 
|---|---|
| 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 | notor!,andor&&,oror|| | 
| 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)