Authoring a KPI
Create a KPI definition with the builder, preview real values, and enable it across your assets.
KPI authoring is a draft-first flow: define the calculation, save it as a disabled draft, preview real values computed over your actual history, and only then enable it. Nothing is scheduled or written until you enable.
To start, go to Analytics → KPIs and click New KPI.
Step 1 — Describe the definition
Fill in the Definition card:
| Field | Description |
|---|---|
| Name | Human-readable name shown in the catalog. |
| KPI key | The output key (lowercase snake_case, for example avg_active_power). Unique within your organization and immutable after creation — choose it carefully. |
| Unit code | The unit of the result, from the platform unit catalog — for example kW, kWh, %, or 1 for dimensionless values. Unknown unit codes are rejected on save. |
| Cadence | How often the engine computes: 1m, 5m, 15m, 1h, or daily (site-timezone calendar days). |
| Description | Optional free text. |
Step 2 — Pick the population
In the Population card, select one or more asset categories and, optionally, a site to narrow the population. The definition applies to every asset that matches — including assets that match later. You must pick at least one category or a site.
Step 3 — Build the calculation
The Calculation card offers two modes.
Builder mode
The builder covers the most common shape: one input variable key (the telemetry variable to read on each matched asset, for example active_power) followed by a chain of shaping operators. Click Add step to append a step and pick its operator:
resample— change the series grain, with an aggregation (avg,min,max,last,sum)fill— fill gaps (prev,zero, ornone, with an optional maximum gap)delta— last value minus baseline over the schedule windowrate— rate of change over the windowcounter_delta— sum of in-window increments of a cumulative counter (baseline lookback, rollover-safe)integrate— time-integral of the series over the window
Each step takes its parameters as JSON, for example {"intervalSeconds": 3600}.
JSON mode
Click Edit as JSON for the full spec shape: a directed graph of nodes and edges with an output node. This is where binary math (add, subtract, multiply, divide), comparisons, per-asset parameter nodes, cycle detection, and KPI-on-KPI compositions live. Back to builder returns to builder mode when the spec still fits the linear shape; richer specs stay in JSON mode so nothing is silently discarded.
As you edit, the How the engine reads this spec panel renders the spec as three cards — Inputs, Operators, and Output — so you can confirm the graph before saving.
Step 4 — Save, preview, enable
- Click Save draft (disabled). The platform validates the spec — structure, operator rules, unit code, KPI key uniqueness, and whether the matched population actually carries the input variables. Validation errors are shown verbatim so you can fix the spec.
- In the Preview the draft panel, pick a time range and click Run preview. The platform computes the calculation over your real history and charts one line per matched asset. A note tells you which storage tier computed the result.
- Click Enable. The platform materializes a KPI variable on every matched asset and the engine starts computing on schedule. A confirmation reports how many assets matched and how many KPI variables were created.
Preview runs the same compiled calculation the scheduler runs. What you see in the preview is exactly what the engine will persist once enabled — there is no separate preview approximation.
Enabling is refused while the selector matches no assets, or while matched assets are missing required per-asset parameter values — see Health & Troubleshooting for the exact messages.
Operator reference
The calculation spec is a graph of typed operators:
| Group | Operators | Notes |
|---|---|---|
| Sources | input, const, parameter | input reads a telemetry variable by key; const is a literal; parameter reads a per-asset value from an asset attribute (dot-namespaced key, for example bess.usable_capacity_kwh). |
| Shaping | resample, fill | Operate on series; resample takes intervalSeconds and an agg. |
| Window aggregations | delta, rate, counter_delta, integrate | Produce one value per asset per schedule window (window scalars). |
| Event detection | classify, sessions | classify maps a series into named states using thresholds, hysteresis, and a minimum-duration debounce; sessions turns state transitions into cycle records. |
| Arithmetic | add, subtract, multiply, divide | Two inputs connected via named ports (for example numerator and denominator). |
| Comparison and logic | gt, lt, gte, lte, eq, and, or, not | Produce boolean series. |
Rules the engine enforces:
- Window scalars are already aggregated.
counter_delta,delta,rate, andintegrateaggregate the whole schedule window per asset — never feed their output intoresample. For a daily total from a cumulative counter,counter_deltaon adailycadence is all you need: the daily window is the day. classifyoutput may only feed asessionsnode, and asessionsnode must be the spec's output — its cycle records are the result.- Binary operators accept series with series (same grain), scalar with scalar, or a scalar broadcast across a series.
dividewrites no point when the denominator is zero — a not-computable window produces a gap, never a fabricated value.- The engine writes one point per asset per window, timestamped at the window start; if the output node is a series, it is averaged over the window.
- KPI-on-KPI: an
inputnode whose variable key is another definition's KPI key reads that KPI's output series. The spec view marks such inputs with aKPIbadge. A definition cannot consume its own output key.
After enabling
The definition detail page shows the spec cards, the live Matched assets list, the Revisions history (every save creates a new immutable revision, with author and timestamp), the health badge, a Preview panel, and Backfills.
To compute history from before the definition was enabled, use the Backfills panel: pick a range and click Queue backfill. Backfills are processed in chunks after live computation ticks, so live results always stay current. Job progress and any errors are listed in the same panel — see Health & Troubleshooting for details.