Methodology · Solar O&M

How the Solar O&M
report is produced.

Every number on the report is derived from a published industry standard, a metered source, or a disclosed approximation. This page documents the formulas, thresholds, data provenance, audit history and known limitations behind the report — for the O&M contractor, the landlord, and anyone else who needs the working shown.

Solar O&M · sample
Methodology v2.7
P1 Urgent — INV 3 offline 26 days · ~9.3 MWh lost
First action: Inspect INV 3 — string/DC side. Dispatch today.
PR (Measured)Poor
54.8%
EYI 63.8% · Period 47.7%
Telemetry coverage
95.2%
of elapsed buckets
IEC 61724-1 · NRS 048-2Audited
Purpose

A technical, hand-off-ready monthly report for the contractor servicing the plant.

The Solar O&M report is generated from the same metering pipeline that produces tenant billing at each MeterX site. Its audience is the O&M contractor, the landlord, and the asset manager. Its job is to surface what needs attention this month — not to defend a billable kWh figure.

Performance

Measured-window Performance Ratio (PR) and Expected Yield Index (EYI) per IEC 61724-1. Both reported side-by-side so the gap between "when we had data" and "over the full period" is visible.

Triage

Five-band health classification (Critical / Poor / Watch / Good / Excellent) drives a P1/P2/P3 dispatch verdict on the cover page. The contractor sees the queue before reading any KPI.

Accountability

Cross-month recurrence detection ("INV 3 has been offline for 56 days") and an optional before/after intervention comparison verify whether maintenance work actually delivered.

Standards

Anchored to recognised industry standards.

The report does not invent its own performance maths. PR, specific yield, capacity utilisation, availability, and the system-loss reference all follow IEC 61724-1:2017. Grid-presence detection follows the supply-quality criteria of NRS 048-2.

IEC 61724-1:2017

Photovoltaic system performance

Defines the framework for the PR / specific yield / availability / capacity-utilisation metrics used throughout this report. Performance Ratio is computed as actual kWh ÷ (reference irradiance × installed kWp), with our measured-window variant restricting the denominator to bucket times where solar telemetry was present (an honest read of plant performance) and a period variant covering the full reporting window (an honest read of what the owner actually received). Both are reported.

NRS 048-2:2007

Quality of supply

South African grid-presence detection follows the NRS 048-2 voltage / current criteria. Each meter declares its signal mode (voltage / amps / wh_pulse) with mode-specific thresholds, so a check meter sitting on the utility incomer can be reliably distinguished from a post-ATS sensor that sees backup-source voltage when the grid is dead.

IEC 61724-1 §10

System loss reference

The 14% lumped system-loss factor used in the EYI denominator (PV-to-AC conversion, soiling, temperature, wiring, mismatch) follows the IEC 61724-1 commercial-rooftop reference value. Per-site calibration via a learned bias factor refines this once a clean 3–6 month baseline is available; until then the report flags the bias factor as "default 1.000".

Eskom 2023 grid factor

Avoided CO₂ emissions

CO₂ avoided is reported at 0.95 kgCO₂/kWh, the published Eskom grid emission factor for 2023. The factor is hardcoded for now and will be promoted to a database setting when Eskom next publishes a revised figure.

Data sources

Provenance for every number on the report.

We do not rely on a single black-box source. Each number on the report traces back to either a metered reading at the inverter, a published satellite reanalysis dataset, or a documented standard reference value. The chain of custody is visible.

Per-inverter AC kWh

Measured at the inverter output via a current-transformer (CT) on each phase. Captured at 1-minute resolution, aggregated to 30-minute buckets at the database layer, then phase-corrected and polarity-corrected at read time. No loss correction is applied — O&M reports use measured AC at the inverter, not display-side adjustments.

  • Hardware: 12-channel IoT M12CH meters, Class 0.5, 12 ksps sampling.
  • Source-of-truth table: raw_readings_clean (TimescaleDB hypertable, 30-day chunk compression).
  • Mapping: meter_channel_maps with effective_from / effective_to so historical buckets get the right mapping if a CT was re-wired mid-period.

Irradiance + weather

Open-Meteo historical / historical-forecast hourly endpoints. ERA5-Land reanalysis blended with CAMS satellite observations. ~10 km grid-cell resolution. Sentinel values (-999, null) filtered at ingest so impossible data can never reach a PR calculation.

  • Variables: shortwave_radiation (GHI), direct_normal_irradiance, diffuse_radiation, temperature_2m, wind_speed_10m, cloud_cover.
  • Storage: site_irradiance_hourly cache, source = OPEN_METEO. One row per hour per site.
  • Cloud cover for the daily-PR overlay is daylight-weighted (Σ cloud × GHI / Σ GHI), not the naïve 24-hour mean.

Grid presence

Each utility-incomer / check meter declares an explicit signal mode (voltage, amps, or wh_pulse) with mode-specific thresholds. Mall incomers default to amps mode at 5 A. The audit summary, the source-attribution loop, and the report's site-outage detection all use this declared mode.

  • Source: logical_meters.grid_presence_signal_mode (migration 139).
  • Outage definition for billing: minutes where the incomer had a row but min amps ≤ 5 A.
  • Site-silent definition for reporting: 30-min buckets where no device at the site reported.

Inverter nameplate

DC kWp and AC kW capture per current-transformer on meter_channel_maps. Captured during commissioning and editable from the meter detail page. Per-inverter capacity gaps (peak kW < X% of AC nameplate) are computed against this value.

  • Fields: nameplate_kwp, inverter_ac_kw, inverter_make, inverter_model, inverter_serial, commissioned_date, solar_tilt_deg, solar_azimuth_deg.
  • Per-CT geometry (tilt / azimuth) is captured but not yet consumed by the v1 PR proxy — earmarked for the Stage 2b Plane-of-Array correction.
KPI definitions

Every metric, with its formula.

The report's Definitions page summarises these in one paragraph each. The expanded versions here include the formulas, the denominator scope, and the reason each variant exists.

PR (measured window, proxy)

Actual kWh ÷ (GHI × installed kWp)

Scope: Buckets where solar telemetry existed.

Honest IEC-61724-style PR proxy. Strips dilution from missing data so a comms / bridge gap doesn't drag the headline number down. This is the diagnostic plant-performance number — the headline KPI on the report.

PR (measured window, EYI)

Actual kWh ÷ (GHI × kWp × (1 − system_loss) × bias_factor)

Scope: Buckets where solar telemetry existed.

Expected Yield Index over the measured window. Same numerator scope as the proxy; denominator also includes the system-loss factor and the per-site bias factor. Carries the five-band health classification (Critical / Poor / Watch / Good / Excellent).

PR (period, proxy)

Actual kWh ÷ (full-period GHI × kWp)

Scope: Entire reporting period.

What the owner actually received. Depressed by coverage gaps and outages by design — the gap between this and the measured-window number is the cost of downtime in performance terms.

Specific Yield

kWh ÷ kWp of installed DC capacity

Scope: Entire reporting period.

The most common O&M productivity number. SA average for fixed-tilt rooftop ≈ 4.5 kWh/kWp/day.

Capacity Utilisation Factor (CUF)

Total kWh ÷ (24 h × days × kWp)

Scope: Time-weighted across inverter active windows.

What % of 24-hour days the plant produced as if running at nameplate. SA average ≈ 18–22%.

Inverter response

Daytime buckets producing > 5% of nameplate ÷ total daytime buckets

Scope: Per inverter, then averaged across the fleet.

Captures "is the inverter responding when it should?" Distinct from telemetry coverage (the inverter might be fine but if the bridge is down we see nothing).

Telemetry coverage

Buckets with a CT row ÷ expected 30-min buckets in the effective window

Scope: Per inverter, then averaged.

Captures metering / comms health. Distinct from inverter response and from site-silent. Clamped at 100% on display (edge cases at the SAST↔UTC boundary can produce 100.x%).

Site silent

Hours during the period where every device at the site was silent

Scope: Site-wide.

Combined grid + comms outage on sites without backup UPS. Sister signal to bills.eskom_down_minutes. Solar generation during these minutes is unmeasured.

% of site median

(this inverter's specific yield ÷ site median specific yield) × 100

Scope: Per inverter; site median across the fleet.

Robust to mixed-roof azimuth bias because every inverter is judged against the site's own typical performance, not an absolute model. Drives the per-inverter peer rank and the "peer outlier" flag (z-score < −1.5).

Peak kW (% of expected peak)

(peak observed kW ÷ min(inverter_ac_kw, nameplate_kwp × (1 − system_loss))) × 100

Scope: Per inverter.

< 60% suggests partial string failure / blown fuse / wiring fault. < 20% in combination with the site verdict triggers a P1 URGENT dispatch. Denominator is the LESSER of AC nameplate and the loss-adjusted DC capacity — for DC-undersized sites (DC:AC < 1.0) the DC term is the binding constraint and the raw AC nameplate is unreachable by design. Round-12 fix (2026-05-27): the original `inverter_ac_kw`-only denominator false-flagged 12 of 16 inverters at Newcastle Mall (DC:AC 0.77) and fired a P1 URGENT on a plant whose EYI was 99.3% green.

PR decline indicator

OLS slope of daily PR-proxy on clear days (cloud cover < 30%)

Scope: Calendar-day offsets, not array indices.

Soiling / degradation signal. Requires ≥ 7 clear days; positive slopes are physically impossible and are suppressed to "—" (panels do not self-clean). Single-month indicator only — defensible soiling rates need multi-month POA-corrected PR.

Reverse flow

kWh measured in the import direction during what should be export

Scope: Per inverter.

Real if a CT is wired backwards (whole-period bias) or if the inverter is consuming during start-up (small magnitudes). Flagged when reverse > 5% of forward generation; site verdict promotes to P1 at > 10%.

Verdict logic

How the report decides what's urgent.

The cover-page verdict strip and the per-inverter outcome columns follow explicit, published rules. Every threshold below is auditable; nothing is "learned" in a way that can drift.

Five-band health classification (measured-window EYI)

Drives the PR tile colour + pill, and gates several escalation rules below.

  • CriticalEYI < 60%
  • PoorEYI 60–70%
  • WatchEYI 70–80%
  • GoodEYI 80–90%
  • ExcellentEYI ≥ 90%

P1 URGENT — dispatch today

Any one of the conditions below fires P1.

  • Long inverter outageany inverter offline > 24 h continuous
  • Capacity collapseany inverter peak < 20% of expected peak (min of AC nameplate and loss-adjusted DC)
  • Site offlinesite silent > 24 h continuous
  • Fleet capacity gap≥ 3 inverters AND ≥ 30% of fleet at < 60% of expected peak
  • EYI criticalmeasured-window EYI < 60%
  • Reverse flowreverse flow > 10% of forward generation

P2 INVESTIGATE — within the week

Any one of the conditions below fires P2 if no P1 condition has fired.

  • EYI poormeasured-window EYI 60–70%
  • Multiple weak inverters≥ 2 inverters at < 60% of expected peak
  • Low coveragetelemetry coverage < 90%
  • Critical incidentany incident emitted as critical severity
  • Reverse flowreverse flow > 5% of forward generation

Intervention "Fixed" criterion

When the report is rendered with a ?split=YYYY-MM-DD parameter (the contractor visit date), each inverter is graded against the before / after windows. The visit day itself is excluded from both windows.

  • Before windowpeak < 10% of AC nameplate
  • After windowpeak > 50% of AC nameplate
  • Evidence days≥ 2 separate days at > 30% NP in the after window

Recurring issue detection (cross-month)

The current period is cross-referenced against the prior calendar month. An inverter must trigger in both.

  • Continuous offlineprior month: offline throughout (total kWh < 10, > 100 reporting buckets) AND current month: outage event > 12 h covering most of the period
  • Persistent low peakpeak < 60% of expected peak in BOTH current AND prior periods
Disclosure

Known limitations, disclosed in advance.

A methodology page that doesn't disclose its own limits isn't credible. The list below is exhaustive as of the current methodology version. Each item is on the roadmap to address.

PR uses Global Horizontal Irradiation, not Plane-of-Array

Full IEC 61724-1 PR computes the denominator on the panel plane (POA), correcting for tilt and azimuth. The current proxy uses GHI (flat horizontal). For SA fixed-tilt rooftop arrays the 14% system-loss factor absorbs most of the GHI→POA gap; Stage 2b on the product roadmap adds explicit POA correction using the cached DNI / DHI / cloud-cover fields and a TypeScript port of the Klein / Liu-Jordan transposition model.

Site bias factor defaults to 1.000

The bias factor is a learned per-site correction that captures tilt, azimuth, shading, module transmittance and inverter efficiency in one number. Until each site has a clean 3–6 month baseline window for calibration, it sits at 1.000. The report flags the default explicitly so the EYI threshold colours are read with that context.

Cell-temperature derate is not modelled

A NOCT-style cell-temperature model (T_cell ≈ T_ambient + (NOCT − 20) × GHI / 800) would let us subtract a temperature-loss kWh from the residual. The cached temperature_2m field supports this but the model is not yet wired in. Stage 2b roadmap.

Recurring-issue look-back is one month

The cross-month detector compares the current period against the prior calendar month only. A multi-month look-back (e.g. "INV 3 has been offline since 1 February" rather than "flagged in last month's report too") is the next analytical step but is deliberately not in the v1 detection.

Irradiance is grid-cell averaged

Open-Meteo's ~10 km grid is interpolated from satellite + reanalysis data, not measured at the panel. Daily-level mismatch is expected on partly cloudy days (cloudy in the model cell, sunny on the actual roof, or vice-versa). Monthly aggregates are robust to ~5%; daily values can drift more.

Outage lost-kWh estimates are not metered

When an inverter goes silent, lost kWh during the outage is estimated as irradiance shape × installed kWp × system loss for the gap hours. Order-of-magnitude correct, not auditable to a single kWh.

Change log

Methodology version history.

The methodology has been through thirteen independently-reviewed rounds between 24 and 27 May 2026. Each round had a discrete outcome captured below; the underlying commits are in version control and the diffs are available on request.

v2.72026-05-27

Peer-outlier-only verdict headline

Newcastle Mall after the round-12 fix dropped from P1 URGENT to P2 INVESTIGATE — but the verdict headline fell through to the generic 'Critical incident detected this period' because no named P2 trigger (fleet capacity gap, EYI band, telemetry, reverse flow) had fired. When peer-outlier events are the only signal, the headline now names up to three flagged inverters with their % of site median: '2 peer outlier inverters flagged — DB2-INV4 at 73% of site median, DB1-INV1 at 74%'. Cosmetic; no metric change.

v2.62026-05-27

DC-undersized + uniform-fleet false-positive fixes

Newcastle Mall (DC:AC 0.77) report screamed P1 URGENT on a plant whose EYI was 99.3% green — 12 of 16 inverters false-flagged as 'low peak capacity' because the denominator was AC nameplate alone. Round 12 fixes: (1) peak-capacity denominator is now min(inverter_ac_kw, nameplate_kwp × (1 − system_loss)) — for DC-undersized sites the DC term is the binding constraint and the raw AC is unreachable by design; (2) peer-outlier detection requires z < −1.5 AND pct_of_site_median < 85% (absolute gate prevents uniform-fleet z-score inflation from firing on inverters at 95%+ of median).

v2.52026-05-27

Methodology defence layer

Standards citations, audit history block, known-limitations disclosure, and Methodology version log added to every report. Each PDF carries a clickable link to this page.

v2.42026-05-27

Intervention comparison + UX polish

Before/after comparison around a contractor visit date (?split= parameter), per-inverter Fixed / Recovered / Degraded outcomes with the ≥ 2 days > 30% NP recovery guard. URL-sync the picker. MTD wording, telemetry-coverage display clamp, PR tile pill placement.

v2.32026-05-27

Cross-month recurring-issue detection

Continuous-offline + persistent-low-peak detectors. Current period cross-referenced against the prior calendar month so "INV 3 offline 56 days" reads as a recurrence rather than a fresh incident each month.

v2.22026-05-27

Operational verdict

P1 URGENT / P2 INVESTIGATE / P3 MONITOR / Healthy verdict strip on every report. Five-band health classification (Critical / Poor / Watch / Good / Excellent) drives the PR tile colour. Issues panel grouped by kind.

v2.12026-05-27

Polish + double-count fix

site_underperformance lost-kWh re-scoped to measured-window only to eliminate double-counting against site-silent and low-peak-capacity entries. Page-break fixes, PR-decline indicator reason text when suppressed.

v2.02026-05-27

Measured-window PR + period PR

Major correctness fix. PR denominator scoped to buckets where solar telemetry existed; bucket-weighted by observable kWp so a non-reporting CT doesn't taint the rest of the fleet. MTD handling for in-progress months. Peer ranking on measured-window PR, not raw specific yield.

v1.x2026-05-24 → 2026-05-25

Initial Solar O&M monthly report

Foundation pass. Single PR variant, single verdict, per-inverter table, irradiance from Open-Meteo, CO₂ avoided at the Eskom 2023 factor. Identified two correctness issues in production reports that drove the v2 rebuild.

Have a question about a number on the report?

Methodology debates are welcome. Send us the specific page + line and we'll show you the underlying calculation and the standards citation behind it.