Skip to main content

SCADA Edge Processing for Power Grids

The Blind Spot: Data Trapped Behind the OT Fenceโ€‹

Every substation is an analytics goldmine. RTUs and PLCs poll sensors every second โ€” voltage, current, frequency, temperature, active power โ€” generating 50,000+ readings per minute across a single substation. In theory, this data could drive real-time grid stability analysis, predictive maintenance, and fault prevention. In practice, almost none of it reaches your analytics systems.

Why? Three compounding problems:

  • OT/IT air gaps โ€” SCADA networks are isolated for security. Getting data out requires crossing a carefully guarded boundary, which operations teams resist for good reason.
  • Volume economics โ€” Shipping 50,000 raw Modbus register reads per minute to a SCADA historian or cloud is expensive, slow, and fills storage with noise. 99% of readings are nominal โ€” "voltage is fine, frequency is fine" repeated forever.
  • NERC CIP compliance โ€” Critical Infrastructure Protection standards restrict what topology data can leave the substation. Substation bus topology, protection relay configurations, and network maps are CIP-sensitive. Sending them to cloud systems creates compliance exposure.

The result: your SCADA historian sees alarm events and operator actions. Your analytics platform sees almost nothing. The rich real-time telemetry that could catch a transformer failure three days before it happens stays locked in the OT network.

That's the opportunity. Not "send more data." It's "send the right data โ€” processed at the edge, compliant by design."

Four Wins, One Pipelineโ€‹

Expanso Edge runs at the substation โ€” on an industrial PC, a hardened edge gateway, or a Kubernetes node in the substation DMZ. It processes Modbus data before it crosses the OT/IT boundary, unlocking four simultaneous wins:

Win #1: Unlock Data Trapped in OT Networksโ€‹

Modbus TCP, DNP3, and IEC 61850 are the languages of operational technology. SCADA historians understand them, but cloud analytics platforms don't. Traditional approaches require protocol converters, data historians, and bespoke middleware โ€” each adding latency, cost, and another system to maintain.

Expanso Edge speaks OT natively and translates to cloud-friendly JSON:

โœ… Modbus TCP socket input โ€” reads directly from RTU/PLC polling streams on port 502
โœ… Register-to-field mapping โ€” REG 40001 becomes voltage_kv, with scaling applied automatically
โœ… Semicolon-delimited to structured JSON โ€” raw REG=40001;VAL=14823 becomes { "voltage_kv": 148.23 }
โœ… No middleware required โ€” one pipeline YAML replaces a protocol converter + historian adapter

Win #2: Edge ML for Fault Classification at Sourceโ€‹

A thermal overload event caught 60 seconds earlier is the difference between a controlled load shed and an unplanned outage. Traditional SCADA alarming uses static thresholds configured in the historian โ€” which can't adapt to operating context, load conditions, or seasonal variations.

Expanso Bloblang processors run fault classification logic directly at the substation:

โœ… VOLTAGE_DEVIATION โ€” transmission voltage outside ยฑ10% of 132 kV nominal (110โ€“145 kV band)
โœ… FREQUENCY_DRIFT โ€” grid frequency outside NERC reliability standard ยฑ0.5 Hz (59.95โ€“60.05 Hz)
โœ… THERMAL_OVERLOAD โ€” transformer or line temperature exceeding thermal rating (75ยฐC threshold)
โœ… LINE_FAULT โ€” current spike combined with voltage drop indicating fault current path

Classification happens in milliseconds at the edge. Fault events arrive at the historian pre-tagged and pre-prioritized โ€” no post-hoc analysis required.

Win #3: NERC CIP Compliance by Designโ€‹

NERC CIP ยงR1.4 requires that electronic security perimeter (ESP) data โ€” including network topology, protection relay configurations, and access control lists โ€” be protected from unauthorized disclosure. Sending raw substation data to cloud systems risks including CIP-sensitive topology information.

Expanso Edge handles this at the pipeline level:

โœ… Strip before egress โ€” topology fields (bus_topology, relay_config, esp_network_map) are deleted in the Bloblang processor before any data crosses the substation boundary
โœ… Aggregate, don't export โ€” instead of raw register values, send KPI summaries. Cloud systems get voltage_avg_kv, fault_count, and uptime_pct โ€” not the raw topology that generated them
โœ… Audit trail stays local โ€” full raw telemetry is archived locally for NERC CIP audit purposes; only processed summaries leave the fence
โœ… Configurable by policy โ€” which fields are CIP-sensitive is configurable in the pipeline YAML, not hardcoded in application logic

Win #4: Better Data Reaches the Historianโ€‹

For data you do send to the SCADA historian, Expanso makes it arrive cleaner, faster, and more useful:

โœ… Pre-parsed fields โ€” historian receives voltage_kv: 148.23 instead of raw REG=40001;VAL=14823
โœ… Normalized units โ€” all values scaled and typed consistently before arrival
โœ… Deduplicated readings โ€” consecutive identical readings suppressed; historian sees state changes, not noise
โœ… Enriched context โ€” substation_id, region, device_id added automatically from environment

Architecture: Traditional SCADA vs With Expanso Edgeโ€‹

Traditional SCADA
RTU / PLC
50,000 Modbus reads/min
โ†“ ALL data crosses OT/IT boundary
Protocol Converter
Modbus โ†’ proprietary format
โ†“ raw, unparsed, unfiltered
SCADA Historian
stores everything, alarming at query time
โ†“
Cloud? Blocked by NERC CIP
โœ… With Expanso Edge
RTU / PLC
50,000 Modbus reads/min
โ†“
Expanso Edge (at substation)
parse โ†’ filter โ†’ classify โ†’ strip CIP fields
โ†“ faults only
SCADA Historian
pre-parsed fault events
โ†“ KPIs only
Cloud Dashboard
12 KPIs/min, CIP-safe
๐Ÿ“ฆ Full archive stays local for NERC CIP audit

What changes:

  • 50,000 reads/min โ†’ 12 KPIs/min โ€” 99.9% volume reduction at the edge
  • Fault classification โ€” VOLTAGE_DEVIATION, FREQUENCY_DRIFT, THERMAL_OVERLOAD tagged before historian ingestion
  • NERC CIP compliance โ€” topology fields never cross the OT/IT boundary
  • Immediate alerting โ€” critical faults reach PagerDuty in milliseconds, not historian polling intervals

If You Know SCADA, You Already Know Expansoโ€‹

Expanso uses familiar SCADA concepts โ€” but as a programmable pipeline:

SCADA ConceptExpanso EquivalentWhat's Better
RTU/PLC pollingPipeline socket input (Modbus TCP)Real-time streaming vs. cyclic polling
Protocol converterBloblang register mappingOne YAML, no hardware appliance
SCADA historianPipeline output (http_client)Multi-destination + pre-filtering
Manual alarm thresholdsBloblang match processorsDynamic, programmable, version-controlled
OT/IT data diodeExpanso edge + field deletionSelective egress with audit trail
Proprietary historian formatStructured JSONOpen, queryable by any analytics tool

What You'll Buildโ€‹

In this tutorial, you'll create a complete SCADA edge pipeline that:

  1. Receives raw Modbus register data via TCP socket from RTU/PLC polling
  2. Parses and normalizes register addresses to engineering units (kV, A, Hz, ยฐC, MW)
  3. Filters nominal readings and classifies fault events at the edge
  4. Routes fault alerts to the SCADA historian and PagerDuty; KPI summaries to Grafana cloud

Prerequisitesโ€‹

  • Expanso Edge installed (installation guide)
  • Access to a Modbus TCP simulator or physical RTU on your OT network
  • Environment variables for historian URL, PagerDuty webhook, and Grafana Cloud

Get Startedโ€‹

Choose your path:

Interactive Explorerโ€‹

Step through all 4 pipeline stages with live before/after comparisons โ€” see raw Modbus data transform into classified fault events

Step-by-Step Tutorialโ€‹

Build the pipeline incrementally:

  1. Parse Modbus Register Data
  2. Filter Nominal Readings at the Edge
  3. Classify Fault Types with Bloblang
  4. Route to SCADA Historian and Alerting

Complete Pipelineโ€‹

Download the production-ready solution โ€” tested at 50,000 readings/minute


Expanso Edge turns your substation from a data silo into a real-time analytics source โ€” while keeping CIP-sensitive topology where it belongs: local.