# Rule expressions

> The fields, operators and functions you can use in a rule condition for each event, with examples that are tested against the rule engine.

Source: https://proxus.io/docs/automate/rule-expressions

A rule's condition is one expression. The gateway checks it against each event of the kind the rule watches
(**Event** on the rule) and fires when it is true. You build it as a sentence in the rule's condition editor, or type
it under **Expression**; both give the same expression, and a typed expression the sentence can say switches back to
it. See [Create a rule](https://proxus.io/docs/automate/rules).

The fields below are what the gateway hands to the rule for each event. Names are case-sensitive; text values are
written in single quotes.

## Operators and functions

- Compare: `=`, `==`, `<>`, `!=`, `<`, `<=`, `>`, `>=`.
- Combine: `AND` (or `&&`), `OR` (or `||`), `NOT`, and brackets `( )`.
- Arithmetic: `+`, `-`, `*`, `/`.
- Functions used in the examples below: `Contains(Field, 'text')`, `Abs(x)`, `ToDouble(text)`.
- Inside a list: `[List][condition]` is true when at least one item of the list matches the condition.

## On Data Received

Each message holds the values one device sent at one moment.

| Field | What it is |
| --- | --- |
| `Topic` | The device ID. |
| `[Payload]` | The list of tag values in the message. Each item has `Key` (the tag name), `NumericValue` (the value as a number), `Value` (the value as text), `PreviousValue` (the previous value as text), `Unit`, `Type`, `Quality` (`Good`, `Bad`, `Uncertain`), `Time` and `PreviousValueTime`. |
| `[MetaData]` | Where the device is. Items have `Key` and `Value`; keys are `DeviceId`, `DeviceName`, `Enterprise`, `Site`, `Area`, `ProcessCell`, `EquipmentModule`. |
| `[Attributes]` | The device's own attributes, as `Key` and `Value`. |

A tag is always checked inside `[Payload][...]`, with its name and its condition in the same brackets. Compare
numbers with `NumericValue`, not `Value`: `Value` is text. A message only contains the tags the device read at that
moment, so a condition on two tags of the same message needs both in it.

```text
[Payload][Key = 'Temperature' AND NumericValue > 28]
```

A tag outside a band:

```text
[Payload][Key = 'Voltage' AND (NumericValue < 215 OR NumericValue > 245)]
```

One device only, by name:

```text
[MetaData][Key = 'DeviceName' AND Value = 'MFB_LYS_TUNNEL_OVEN'] AND [Payload][Key = 'Zone1Temp' AND NumericValue > 200]
```

All devices whose name contains a word:

```text
[MetaData][Key = 'DeviceName' AND Contains(Value, 'PowerGenerator')] AND [Payload][Key = 'Temperature' AND NumericValue > 85]
```

A jump of more than 5 since the previous reading:

```text
[Payload][Key = 'Pressure' AND Abs(NumericValue - ToDouble(PreviousValue)) > 5]
```

A rise of more than 10 % since the previous reading:

```text
[Payload][Key = 'FillRate' AND ToDouble(PreviousValue) <> 0 AND (NumericValue - ToDouble(PreviousValue)) / ToDouble(PreviousValue) > 0.10]
```

Several conditions, one of them negated:

```text
[Topic] = 'Device123' AND [Payload][Key = 'Pressure' AND NumericValue > 100] AND NOT [Payload][Key = 'Temperature' AND NumericValue < 25]
```

Two device attributes:

```text
[Attributes][Key = 'Location' AND Value = 'FactoryA'] AND [Attributes][Key = 'Priority' AND Value = 'High']
```

## On Status Changed

| Field | What it is |
| --- | --- |
| `DeviceId`, `DeviceName` | The device. |
| `CurrentConnectionStatus` | `Unknown`, `Connected` or `Disconnected` (or `0`, `1`, `2`). |
| `PreviousConnectionStatus` | The status before this change. |
| `ConnectionDuration` | How long the previous status lasted, in seconds. |

```text
CurrentConnectionStatus = 'Disconnected'
```

A device that came back after less than a minute away:

```text
CurrentConnectionStatus = 'Connected' AND PreviousConnectionStatus = 'Disconnected' AND ConnectionDuration < 60
```

## On Log Received

| Field | What it is |
| --- | --- |
| `Time`, `Level`, `Source`, `Category`, `Message` | When, how serious (for example `Warning`, `Error`, `Critical`), which gateway, which part of it, and the text. |
| `ReasonCode` | A stable code for the kind of event, where the product sets one. Prefer it to matching `Message` text. |
| `EventId`, `CorrelationId`, `Operation`, `EntityType`, `EntityId`, `Fingerprint`, `OccurrenceCount`, `Diagnostic` | More detail, where present. |

```text
Level = 'Critical' OR Level = 'Error'
```

```text
Level == 'Error' && Contains(Category, 'FieldbusActor')
```

Log entries written by the rule engine and by notifications themselves are not passed to rules.

## On Metrics Received

The read statistics of one device, sent after each read cycle.

| Field | What it is |
| --- | --- |
| `Device` | The device. |
| `TotalRequests`, `SuccessfulRequests`, `FailedRequests`, `ResponseCount` | Read requests so far. |
| `ReadErrorCount`, `ConnectionErrorCount`, `ReadErrorPercentage` | Errors so far, and the share of failed reads in percent. |
| `AverageResponseTime` | Average response time of the device. |
| `LastCommunicationTime`, `LastDataReceivedTime` | When the device last answered and last sent data. |
| `TotalDataReceived`, `ProcessedDataCount`, `SleepModeTransitionCount` | Counters. |
| `DataAccuracy`, `DataCompleteness`, `DataFreshness`, `DataIntegrity`, `DataConsistency` | Data quality scores. |

```text
ReadErrorPercentage > 10
```

```text
FailedRequests > 100 && ReadErrorPercentage > 20
```

```text
DataAccuracy < 80
```

## Common mistakes

| Written | Problem | Write instead |
| --- | --- | --- |
| `[Temperature] > 80` | Tags are not fields of the message. | `[Payload][Key = 'Temperature' AND NumericValue > 80]` |
| `[Payload][Key = 'Temperature' AND Value > 80]` | `Value` is text. | `NumericValue > 80` |
| `[Payload][Key = 'A'] AND [Payload][NumericValue > 5]` | The two parts may match two different tags. | Put name and condition in one bracket: `[Payload][Key = 'A' AND NumericValue > 5]` |

An expression the gateway cannot read never matches. The rule's **Logs** then show that the criteria could not be
compiled.

## What's next

- [Create a rule](https://proxus.io/docs/automate/rules): use the expression in an alarm rule.
- [Add a rule action](https://proxus.io/docs/automate/rule-actions): send a notification or forward data when the rule fires.
- [Troubleshoot automation](https://proxus.io/docs/troubleshoot/automation): rules that do not match or do not fire.
