A condition is an expression that tests something and gives one value when the test holds and another when it does not. {status}>0 ? 1 : 0 reads "if status is above 0, then 1, else 0". Conditions let one sensor field turn a raw code into a clear state, or depend on another sensor. You write them in the expression, or with the condition builder on the Conditional tab of the sensor field's dialog.

{status}>0 ? 1 : 0 turns every open code into 1.[Ignition#v]==1 ? ([Engine RPM#rpm]<900 ? 1 : 0) : 0.{load} > 80 ? 2 : ({load} > 40 ? 1 : 0) gives three load levels.{in4} == 1 ? {can_rpm} : 0 reports engine speed only with the ignition on. Do not do this with a fuel level: the else value reads as an empty tank. To drop bad readings, use bounds; see Calibration tables.A condition always gives a number. The test itself is true or false, and the app refuses to save a field whose result can be true or false. Write <test> ? 1 : 0 to turn a test into 1 or 0.
On every message the device sends, the app computes each field in this order:
A chain of conditions, a ? x : (b ? y : z), reads as "if a, then x; else if b, then y; else z". The condition builder writes and reads chains in exactly this form, one row per test.
Watch what happens when a message does not carry a value the test needs:
| Test | Parameter missing from the message | Result |
|---|---|---|
{in4} == 1 ? 1 : 0 |
== and != treat it as not equal |
The else value, 0 |
{status} > 0 ? 1 : 0 |
>, >=, <, <= need a number |
No value for that message |
[Ignition#v] == 1 ? 1 : 0 |
A referenced sensor with no value | No value for that message |
{in4} == 1 ? {fuel_lvl} : 0 |
The value of the branch the test picks | The else value, 0 |
[Ignition#v] == 1 && {in4} == 1 ? 1 : 0 |
A parameter the app reaches, in an expression that also reads a sensor | No value for that message. With the ignition off, the app stops at the first test and gives 0. |
The fourth row matters for readings such as fuel. When the test holds but the chosen value is missing, the app takes the else value. A fuel field written that way reads 0 litres instead of nothing, which can look like a drain. Put a reading you rely on in the test as well, or leave the condition out and use bounds.
The calibration table converts whatever the condition returns. Someone measured its points against the value the field produced at the time. A condition added later changes which value that is, and the table would then convert the wrong numbers. So the app keeps the order strict:
A test can read any field of another sensor on the same device, written [Sensor name#field]. It gets that field's final value, after its own expression, calibration and bounds. The app computes the other sensor first. Two sensors cannot read each other: the hint names the loop and Save stays off.
Tests may mix sensor references and parameters: [Engine RPM#rpm] > 300 ? {in4} : 0.
These conditions run on the demo devices.
| Sensor and field | Condition | Reads as |
|---|---|---|
| Cargo door | {status}>0 ? 1 : 0 |
If the status code is above 0, then 1 (open), else 0 (closed). |
| Idling | [Ignition#v]==1 ? ([Engine RPM#rpm]<900 ? 1 : 0) : 0 |
If the ignition is on: 1 when the engine runs under 900 rpm, else 0. With the ignition off: 0. |
| Driver behaviour, harsh braking | {event_code}==1 ? 1 : 0 |
If the event code is 1, then 1, else 0. |