AI Solar Panel
007 Monitoring and Anomaly Detection 1,562 words · 7 min

What Your Smart Meter Dashboard Isn’t Telling You

A friend of mine lost 8% of his array output for eleven weeks and his monitoring never flinched. One panel’s bypass diode had failed. His in-home display showed the usual numbers, his supplier app showed the usual export, his spreadsheet showed a normal summer. The fault only surfaced because a neighbour with an identical roof mentioned a figure that was too high.

Nothing in that chain was broken. The IHD was accurate, the app was accurate, the spreadsheet arithmetic was right. The problem is that every one of those layers had already destroyed the specific information needed to see the fault, and he had never checked which information that was.

If you are going to lean on a dashboard to tell you something is wrong, you need to know its detection floor first. That means working out, in kW and kWh and minutes, what size of fault your monitoring can actually resolve, and how long it takes to tell you.

Your meter measures a boundary, not a house

A UK smart meter sits at the supply boundary and records net active energy per phase. That is the whole of what it knows. Solar, battery, immersion diverter and EV charger all live behind it, and the meter’s import register only moves when the net flow at that point is inward.

Here is what that does to your data. Say your Eddi is dumping 2.4 kW into the immersion while the array puts out 2.4 kW. The house is genuinely consuming 1.2 kWh across that half hour. Your meter records this:

{
  "count": 48,
  "results": [
    {"consumption": 0.0,
     "interval_start": "2026-06-21T12:30:00+01:00",
     "interval_end":   "2026-06-21T13:00:00+01:00"},
    {"consumption": 0.0,
     "interval_start": "2026-06-21T12:00:00+01:00",
     "interval_end":   "2026-06-21T12:30:00+01:00"}
  ]
}

Zero. Not “no data”, not null, an affirmative zero from the Octopus /v1/electricity-meter-points/{mpan}/meters/{serial}/consumption/ endpoint. Any model you build on import data alone will conclude your house draws nothing between 11:00 and 15:00 in June. Apps that claim to break your usage down by appliance (Loop, Hugo, most supplier “insights” tabs) are inferring from this same netted signal. That is pattern-matching on a waveform, not measurement, and behind-the-meter generation is exactly the condition that breaks the inference.

The export-limited blind spot

Now the interesting part, because this is what hid the dead panel.

His system: 5.4 kWp (12 × 450 W, two strings of six), one hybrid inverter, G98 export limitation at 3.68 kW. On a clear June noon the array delivered about 4.6 kW AC after temperature and system losses. House baseload around 0.5 kW. Potential export 4.1 kW, clipped by the limiter to 3.68 kW.

One panel bypassed takes roughly a sixth of one string’s voltage out, so the array drops about 8%, to 4.22 kW. Potential export becomes 3.72 kW. Still above 3.68. The meter’s export register does not move. Not by a rounding error, not by a decimal place: the entire fault was absorbed by headroom he was already throwing away.

Battery charging does the same thing with a different mechanism. If surplus is going into a 9.5 kWh pack, an 8% generation shortfall means the pack finishes charging around twenty minutes later and the meter sees nothing unusual at all. Your buffers are the things that make a solar and battery system economic, and they are also the things that swallow small faults whole.

Averaging is where the evidence goes

Half-hourly settlement data is a sum, and a sum of 1,800 seconds cannot distinguish shapes. A 3 kW load running for four minutes and a 400 W load running for the full thirty minutes both arrive as 0.2 kWh. Modulating loads (heat pump compressors, inverter-driven fridges, a diverter chasing a cloudy sky) are flattened into a single number that resembles none of their actual behaviour.

Live data is better but bounded too. A ZigBee CAD such as the Hildebrand Glow publishes instantaneous demand roughly every 10 seconds over MQTT, which is genuinely useful, and still means every transient shorter than that is gone. Inrush current, brief clipping events, the relay chatter of a failing contactor: not in your data, at any price.

Resolution on the underlying registers is fine, incidentally. Half-hourly values come as differences of cumulative registers reported to 0.001 kWh, which is a 2 W average over the interval, and the errors do not accumulate. It is worth saying plainly because people chase precision when the actual problem is aggregation and latency.

Latency, and the missing-data trap

SourceResolutionTypical lag
Glow CAD, local MQTT10 sunder a second
Inverter local Modbus (GivTCP, Fronius Solar API)1 to 5 snegligible
GivEnergy cloud API5 min5 to 15 min
SolarEdge monitoring API15 min15 to 20 min, 300 calls/day cap
DCC half-hourly via Bright or supplier app30 minbatched, often next morning
Octopus consumption API30 minusually under 24 h, sometimes 48

Read that column on the right as your worst-case time to detection. If your only export data comes from the DCC path, a fault that occurs on Friday afternoon is not visible until Saturday, and if your check is a weekly spreadsheet refresh you are looking at a five-day exposure. At 15p/kWh SEG on a 25 kWh summer day, a total outage costs about £3.75 a day. Not ruinous. A 30% string fault that persists from May to September, unnoticed, is a different number.

Missing data is the sharper hazard. When a Growatt ShineWiFi-X or a SolarEdge gateway drops off Wi-Fi, the portal reports zeros, not gaps. Feed those zeros into a rolling baseline and the baseline sags, which raises your tolerance for genuine underperformance at exactly the wrong moment. Your anomaly rule then has to distinguish three states that all look identical on the wire: inverter dead, logger dead, night. Most homebrew rules treat absent as zero and are therefore blind by construction.

Clock skew will fake correlations for you

Octopus returns ISO timestamps with a local offset (+01:00 in summer). Most DCC-derived feeds hand you naive local times. Inverter cloud APIs report in whatever timezone the installer set, and datalogger clocks drift, sometimes several minutes a month.

Align two of those naively and you will produce self-consumption above 100%, phantom “export while importing” intervals, and a battery that appears to discharge before the evening peak begins. I have seen someone spend a weekend investigating a control-logic bug that was a one-hour BST offset. Normalise everything to UTC on ingest, then convert once at display, and check the alignment by cross-correlating one clear day’s inverter power against meter export to find the lag empirically.

Write the detection spec before you trust the dashboard

The useful move is to invert the question. Stop asking what your dashboard shows and start listing the faults you care about, then ask which channel would carry each one, at what magnitude, against what noise. One block per failure mode:

- fault: one panel bypassed (string of 6 × 450 W)
  signature: -8% array power, every clear-sky hour
  visible_in: inverter AC power, 11:00-14:00 window
  invisible_in: meter export register (export-limited, zero delta)
  noise_floor: ±4% (soiling, cell temp, irradiance model error)
  latency: 5 min local Modbus, 20 min cloud
  rule: 5-day median noon kW vs clear-sky model, alert below -6%

- fault: datalogger offline
  signature: absent records, reported as 0 kWh
  visible_in: record count per day (expect 288 at 5 min)
  latency: 1 h
  rule: alert if records < 270 on any day, separately from any kWh rule

Two things fall out of writing this down. First, several faults you assumed were covered turn out to have no channel at all: cell imbalance in the battery, a reversed CT clamp on a Shelly Pro 3EM, slow PID degradation at half a percent a year. Second, the noise floor line forces honesty. A ±4% floor means a 3% fault is undetectable no matter how clever your model, and you should stop pretending otherwise and either add per-string data or accept the blind spot deliberately. The broader framework for turning those specs into rules that fire on real faults and stay quiet on cloudy Tuesdays is covered in monitoring and anomaly detection.

Expect discrepancies between sources even when everything is healthy, by the way. A smart meter is certified to around ±1% at reference load and looser outside it; a CT-clamp monitor claims ±1 to 2% and does worse below about 10% of its rated current; an inverter’s own generation figure carries its own few percent. Three sources disagreeing by 4% is a calibration fact, not a fault, and you need to establish that offset on a known-good week so you have something to compare against later.

One test, this weekend, on the next cloudless day. Pull your inverter’s power at 5-minute resolution and your meter’s export at half-hourly for the same noon window, convert both to UTC, and work out what fraction of a 400 W generation loss would show up at the meter. If the answer is zero, you have just learned that your export data is a billing record and nothing more, and that every fault rule you own needs to live on the inverter side of the boundary.