Skip to content

Power Dashboard

A full-stack electrical power monitoring system with real-time WebSocket data, eight simulated meters, ISA 18.2 alarm management, interactive one-line diagrams, and historical trending.

Python FastAPI React WebSockets SQLite ISA 18.2 Recharts
// the problem

Power monitoring dashboards are either too simple or too expensive

Electrical Power Monitoring Systems for data centers and industrial facilities tend to fall into two categories: basic single-page dashboards that show raw meter readings with no context, or enterprise SCADA systems that cost six figures and take months to deploy. There isn't much in the middle.

At work, I spend time around control systems that deal with real power data: voltage, current, power factor, breaker states. I wanted to build something that was a real EPMS, with proper alarm management and a useful one-line diagram, built with open-source tools on a standard stack.

The ISA 18.2 alarm management standard was a specific goal. Most hobby projects skip alarm logic entirely or implement it as a simple threshold check. ISA 18.2 defines four priority levels, acknowledgment states, and return-to-normal transitions that reflect how alarms actually work in real facilities. I wanted to implement that properly.


// how it works

Eight simulated meters, live WebSocket feeds, and a real alarm engine

The backend simulates eight power meters across a simplified data center topology: a main service entrance, two distribution panels, and five branch circuits at the rack level. Each meter generates realistic-looking voltage, current, and power factor readings with configurable variance. The simulation is designed to match the behavior of a real facility under normal and fault conditions.

The WebSocket layer pushes meter updates to the frontend every second. The React UI renders a live numerical display for each meter and updates the one-line diagram dynamically based on current readings and breaker states. Historical data is written to SQLite and served through a REST endpoint that powers the trending charts.

The alarm engine evaluates four ISA 18.2 priority levels: critical, high, medium, and low. Each alarm has an activation threshold, a return-to-normal threshold (with hysteresis), and an acknowledgment state. Unacknowledged alarms display differently from acknowledged ones. The alarm summary view shows active, acknowledged, and historical events in separate lists.

The one-line diagram is drawn in SVG with React. Transformers, breakers, meters, and buses are all individual components. Breaker state changes are animated, and alarm conditions change the color and styling of the affected element. Clicking any element brings up its detail panel.


// the technical details

Alarm state machines, SVG layout, and simulation fidelity

Implementing ISA 18.2 correctly required thinking of each alarm as a state machine rather than a simple threshold check. The states are: normal, active unacknowledged, active acknowledged, return-to-normal unacknowledged, and shelved. Each state has valid transitions and rules about what actions are permitted. Getting the acknowledgment flow right was the part that took the most iteration.

The hysteresis requirement was interesting to implement. A naive alarm that activates above a threshold and clears below the same threshold will chatter when the value oscillates near the limit. ISA 18.2 addresses this by requiring a separate return-to-normal setpoint that's offset from the trip setpoint. The implementation uses two limits per alarm configured in the backend.

The SVG one-line diagram posed a layout challenge. One-line diagrams follow conventions that don't map naturally to standard web layout systems. Power flows from top to bottom, buses run horizontally, and feeders branch off vertically. I built a grid-based placement system that positions each SVG element by row and column, which made the diagram easier to maintain and extend without manually managing pixel coordinates.

The simulation had to balance realism with predictability. Pure random noise produces values that don't tell a useful story. The simulation uses mean-reverting random walks with per-meter parameters, so readings look realistic but stay within sensible bounds.