← Articles
Networking/8 min read/ views

IEC 61850 Reporting: Why Buffered and Unbuffered Reports Behave So Differently

How BRCB and URCB blocks feed substation data to SCADA: datasets, trigger options, buffer time, and the reservation fights that starve a client.

NetworkingSCADATroubleshootingCommissioningTags

The client that connects fine and then hears nothing

A protection engineer hands you a substation IED, gives you the IP and the MMS port, and you connect on the first try. Browsing the model works — you can read PROT/PTOC1.Op.general, you can poll the measurands under MMXU1. Then you sit and wait for status changes and nothing arrives. A breaker trips on the bench and your SCADA log stays empty.

Nothing is broken. You connected to the IED, but you never enabled a report, and in IEC 61850 that is the whole game. Unlike Modbus or a plain OPC UA subscription, the interesting data does not flow because you opened an association — it flows because a Report Control Block is enabled, pointed at a dataset, and configured to trigger on the events you care about. Get any of those three wrong and the link looks alive while telling you nothing.

Reports, not polls

IEC 61850-7-2 (the ACSI, mapped onto MMS by 61850-8-1) defines reporting through two objects that live inside a logical node — almost always LLN0:

  • URCB — Unbuffered Report Control Block.
  • BRCB — Buffered Report Control Block.

Both point at a dataset (DATA-SET), an ordered list of data attributes like XCBR1.Pos.stVal, XCBR1.Pos.q, XCBR1.Pos.t. When a member of that dataset changes in a way the block is told to notice, the IED assembles a report and pushes it to the client. There is no request. This is report-by-exception done at the device, and if you've configured DNP3 unsolicited responses the mental model transfers cleanly — but the plumbing is more explicit and more of it is on you.

The difference between the two blocks is one word, and it's the word that matters at 2 a.m.: buffered.

What buffering actually protects

A URCB only reports while a client is connected and has the block enabled. If the association drops — radio glitch, switch reboot, you restart the SCADA front end — any events that occur during the gap are gone. When you reconnect and re-enable, you get the next change, never the ones you missed. For measurands sampled every few seconds that's usually fine. For a breaker that changed state while you were disconnected, it's a lie by omission.

A BRCB keeps an internal event buffer. When no client is reading, or the association is lost, qualifying events pile up in that buffer with an EntryID stamped on each. On reconnect the client reads the last EntryID it processed, writes it back into the BRCB, and the IED replays everything after that point. That's how you close the gap across a comms outage without a general interrogation flood.

The catch: the buffer is finite. Vendors don't advertise the depth loudly, and it's often a few hundred to a couple thousand entries. Sit disconnected long enough on a chattering dataset and the oldest entries fall off. When that happens the IED sets the BufOvfl flag in the next report header. If your SCADA driver ignores that flag, you'll silently trust a picture that has holes in it — treat BufOvfl as a trigger for a full general interrogation, not a log line.

Rule of thumb I use: breaker positions, protection operate/pickup, disconnector status, tap position — anything where a transition is the event — goes in a buffered dataset. Analog measurands under MMXU that you already deadband and periodically refresh can live on an unbuffered block. Don't dump everything into one giant BRCB; you're paying buffer memory for data that didn't need it.

The three knobs that decide whether a report ever fires

Once the block points at the right dataset, three settings decide behavior. Every reporting complaint I've debugged came down to one of them.

TrgOps — trigger options. A bitstring choosing what counts as an event:

  • dchg (data-change) — value changed. The usual one for status.
  • qchg (quality-change) — quality changed, e.g. a point went to questionable or invalid.
  • dupd (data-update) — the attribute was updated even if the value is identical (used for things like a re-issued command).
  • period (integrity) — periodic dump of the whole dataset on a timer, change or no change.
  • gi (general-interrogation) — sends the full dataset on demand when the client writes GI = TRUE.

The classic mistake: a dataset full of stVal and q members, but the URCB only has dchg set. Quality flips to invalid, value never changes, no report. If you care about a point going bad — and on protection data you do — enable qchg too, and make sure q is actually a member of the dataset.

bufTm — buffer time (ms). How long the IED waits, after the first change, to gather more changes into a single report. Set it to 0 and a three-phase event becomes three reports arriving microseconds apart. Set it to something like 10–50 ms and the whole event coalesces into one report with all the changed members — far easier on the SCADA and it preserves the "these changed together" grouping. This is the closest thing 61850 has to a debounce, and it's underused.

intgPd — integrity period (ms). With period enabled, the interval for the full-dataset refresh. This is your safety net against a missed change-of-state on a URCB — set it to something like 60000 (60 s) so the picture self-heals even if a dchg report was lost. On a BRCB you often don't need integrity at all because the buffer already covers you; running a tight integrity period there just wastes bandwidth.

The reservation trap

This one costs the most field time and shows up as "it worked yesterday."

A single RCB instance serves one client at a time. To handle multiple SCADA masters — a primary and a backup, or SCADA plus an engineering tool — vendors instantiate several copies: LLN0.RP.urcbStatus01, ...02, ...03, and so on. Each client must reserve and enable its own instance.

For a URCB, a client reserves by writing Resv = TRUE; that instance is now yours until you disconnect. For a BRCB, reservation uses ResvTms (Edition 2): a positive value reserves the block for that many seconds, and -1 reserves it permanently until released. The point of reservation is that no other client can steal your buffer position out from under you.

Where it goes wrong: two clients configured for the same instance number. The first one grabs it, the second connects, finds it reserved, and gets nothing — no error dialog, just silence. Or a redundant SCADA pair both try urcbStatus01 and flap the reservation back and forth on every failover, so each side intermittently loses reports. The fix is boring and mandatory: give every client its own RCB instance in the SCL, and write it down, because the IED won't warn you.

ConfRev: the number that makes a client reject good data

Every RCB carries ConfRev, a configuration revision counter for the dataset it serves. When someone edits the dataset — adds a point, removes one, reorders members — a well-behaved tool bumps ConfRev. The client is supposed to compare the ConfRev in each report against what it expects and reject reports that don't match, because a dataset whose membership changed means the client's positional decoding is now wrong.

The failure I see: an integrator edits the .CID file to add three points to a dataset, downloads it, but the SCADA side still has the old dataset definition and the old expected ConfRev. Now either the client rejects every report (best case — you notice), or a sloppy driver decodes anyway and maps the new members onto the wrong tags (worst case — the breaker status shows up under a measurand). After any dataset change, re-export the model to SCADA and confirm both sides agree on ConfRev before you trust a single value.

A commissioning order that avoids the silent failures

When I bring up 61850 reporting on a new IED, I go in this sequence:

  1. Read the model and confirm the datasets exist and contain stVal, q, and t for each status point — quality and time, not just value.
  2. Pick the right block type per dataset: BRCB for transitions, URCB for cyclically refreshed analogs.
  3. Reserve my own RCB instance and record which instance number belongs to which client.
  4. Set TrgOps for what the data actually needs — dchg + qchg for status, add period where a self-heal refresh matters.
  5. Set bufTm to coalesce simultaneous changes (10–50 ms), and intgPd for the integrity refresh where used.
  6. Write RptEna = TRUE. Only now do reports flow.
  7. Fire a GI = TRUE to pull the initial full picture, then force a real transition and confirm the report arrives with the right EntryID, RaisonCode (reason for inclusion), and quality.

Miss step 6 and you get the client from the top of this article — connected, browsing, and deaf. The connection was never the point. The enabled report is.