04 Advanced Variables
Multi-select, repeat panels, and hidden variables for per-machine OEE.
In this tutorial you'll build a dashboard that shows OEE metrics and production runs per machine. Panels repeat automatically for each selected machine:

What you'll learn
Multi-select and "Include All" for variables
Automatically repeating panels (Repeat)
Hidden variables for time rounding (OEE API)
Per-machine OEE with POST queries
Brief overview: time series data via the API
Prerequisites
Working with Variables completed
Understanding of dashboard variables, JSONata, and API queries
Multi-select and Include All
In Part 1 the machine variable held a single value. For a dashboard showing multiple machines at once, you need multi-select.
Create a new dashboard with a
sitevariable as in Part 1Create a variable
machines(plural) with these settings:
Variable type
Query
Name
machines
Label
Machine
URL
machines
Root selector
$.data
Add under URL Query Params:
site
${site}
Columns:
name(Name),uuid(UUID)Under Selection options:
Enable Multi-value
Enable Include All option
Sort: Alphabetical (asc)
Refresh: On dashboard load
You can now select individual machines from the dropdown or choose All for every machine at the site.
Note the variable name machines (plural). This signals that the variable can hold multiple values and avoids confusion with the single-value machine variable from Part 1.
Repeating panels (Repeat)
Instead of creating separate panels for each machine, let Grafana repeat panels automatically.
Configure a row with Repeat
Create a Row (click Add > Row)
Click the gear icon on the row
Set Title to
${machines:text}Under Repeat for: select the
machinesvariable
Grafana now creates a separate row for each value of the machines variable. Within each row, ${machines} is replaced by the UUID of the respective machine.

Panels inside a repeat row automatically use the current iteration value. While ${machines} normally contains multiple UUIDs, inside a repeat row it resolves to exactly one UUID per iteration.
You can only edit the first repeated element — whether row or panel. The remaining copies are automatically regenerated from the first element on every refresh.
Hidden variables: time rounding for OEE
The productivity-metrics endpoint expects timestamps aligned to 10-minute intervals. Grafana's built-in time variables (${__from}, ${__to}) return arbitrary timestamps. The solution: custom variables that round the selected time range to 10-minute intervals. Since these variables are only relevant for queries, they are implemented as hidden variables — they don't appear as dropdowns in the dashboard. If needed, you can include their value using ${start} or ${end} in panel titles for transparency.
Create the start variable
Open Dashboard Settings > Variables > + New variable
Configure:
Variable type
Query
Name
start
Hide
Variable (fully hidden)
Source
Inline
Data
{"time": ${__from}}
Root selector
see below
Refresh
On time range change
Root selector (JSONata expression):
600000 milliseconds = 10 minutes. The formula rounds the timestamp down to the nearest 10-minute interval.
Create the end variable
Create a second hidden variable end with the same settings, but:
Name
end
Data
{"time": ${__to}}
Refresh: On time range change is critical here. Without this setting, start and end would only be calculated when the dashboard loads and wouldn't update when you change the time range.
Per-machine OEE with Repeat
Now you'll combine repeat rows with the productivity-metrics endpoint.
OEE Stat panel
Create a Stat panel inside the repeat row:
Method
POST
URL
machines/${machines}/productivity-metrics
Root selector
$.data
Expand Parsing options & Result fields and add a Column:
productivity.score
productivity
Number
Expand URL options and configure the request body:
Body Type
Raw
Body Content Type
JSON
Body Content
{"datetime_ranges": [{"start": "${start}", "end": "${end}"}]}
Make sure Body Content Type is set to JSON (not Text). The ENLYZE API rejects requests with Content-Type: text/plain (HTTP 422).
Configure the panel:
Unit: Percent (0.0-1.0)
Color mode: Background
Thresholds: Red (base), Yellow (0.6), Green (0.8)
Value Mapping:
null→ "NO DATA" (Grey)
Why Columns instead of Root Selector?
It would be tempting to extract the score directly in the root selector, e.g. $.data[0].productivity.score. This works as long as the API returns data. However, if a machine wasn't running during the selected time range, $.data is an empty array. Accessing [0] then fails and Grafana shows an error instead of an empty panel.
The solution: set the root selector to $.data and extract the value via a Column (productivity.score). If there's no data, the column returns null. You can then display this null value as "NO DATA" using a Value Mapping.
Additional OEE panels
Create panels for the remaining metrics using the same pattern:
Availability
$.data
availability.score
Performance
$.data
performance.score
Quality
$.data
quality.score
Configure a value mapping for null → "NO DATA" in grey on all panels. Not all machines provide quality data, and machines without production in the selected time range show "NO DATA" for all metrics.

Production runs table
Add a Table to the row showing the production runs for the respective machine:
Method
GET
URL
production-runs
Query Params
machine=${machines}, start=${__from:date:iso}, end=${__to:date:iso}
Root selector
$.data
Add columns: start (Start, Timestamp), end (End, Timestamp), production_order (Order, String), productivity.score (OEE, Number).
Excursus: time series data via the API
For time series data (e.g. temperature curves, throughput) the ENLYZE API offers the timeseries endpoint:
The resampling_interval parameter (in seconds) reduces the data volume. Without resampling, queries can return very large datasets.
Limitations:
The API paginates responses (max 100 entries per page). The Infinity plugin only supports automatic pagination experimentally.
For time series visualizations, the ENLYZE data source (the dedicated Grafana plugin) is the better choice, as it handles pagination and resampling automatically.
Tips
Variable Refresh: "On dashboard load" for master data (sites, machines). "On time range change" for time-dependent calculations like the rounded timestamps.
Variable order: The order in Settings determines the evaluation order:
site→machines→start→end.Debugging Repeat: If repeat panels don't appear, check that the variable is correctly selected under Repeat options on the row and that it contains multiple values.
POST Body: The body is specified as a string. Variables like
${start}are replaced before sending. Ensure correct JSON syntax with quotes.
Next steps
Production Status Dashboard — Constant variables and live status displays for multiple machines
Last updated