Skip to content
fortuechip-automationPublic

About

Independent OPC UA fleet-state viewer for a BESS digital twin

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bess-viz

A read-only fleet-state viewer for a BESS (battery energy storage system) digital twin. It polls the plant's OPC UA server directly and renders every inverter and battery on a single page.

Why it exists

The lab it belongs to already has two views of the plant:

Layer Tool Answers
SCADA / control Ignition Perspective "what is it doing, and let me change it"
Historian Grafana + TimescaleDB "what did it do over the last week"
Fleet portal bess-viz "what are all 30 devices doing right now, unmediated"

bess-viz reads the plant's OPC UA server directly, and renders it with no SCADA layer in between. Its telemetry ultimately originates in the same database as the others — the OPC bridge populates its tags by selecting the latest rows — so this is not an independent data source, and it would be wrong to claim otherwise.

What it is independent of is the SCADA layer: no named queries, no tag bindings, no panel logic. And the OPC surface carries something the database does not. Command tags such as Site/P_set_kW are staged inputs: written by an operator, initialised once at bridge startup, and never refreshed from telemetry afterwards. They hold intent, not state.

That distinction is the reason this exists. When the panel and the historian disagreed about a setpoint, the raw OPC view showed a stale operator command that neither of them was displaying — because neither of them shows that layer.

Three properties define it:

  • Read-only. There is no write path. It never issues a command or writes a tag.
  • Stateless. It holds the current snapshot and nothing else. No history, no database.
  • Unmediated. It shows the OPC UA layer as it is, with no SCADA in the path. Its telemetry still comes from the same database everything else reads.

How it works

  OPC UA server            poller                   web                browser
  (simulator)      -->  asyncua client   -->  fleet_state.json  -->  static page
   :4840                every 2 seconds        (atomic write)         + /api/fleet

The poller discovers the namespace on connect, reads the fleet, and writes a single JSON snapshot atomically (write to .tmp, then os.replace) so a reader never sees a half-written file. The web half is Python standard library only — no framework, no dependencies — and serves the snapshot at /api/fleet with a staleness flag set when the data is older than three poll cycles, so a dead poller shows as stale rather than as plausible-looking frozen numbers.

Configuration

All configuration comes from the environment, so the same image or checkout runs against any plant without an edit. Defaults are the safe/local choice; a deployment opts in to anything wider.

Variable Default Purpose
BESS_OPC_ENDPOINT opc.tcp://192.168.1.71:4840 OPC UA server to poll
BESS_VIZ_DATA <repo>/data/fleet_state.json (web), /data/fleet_state.json (poller) shared snapshot file
BESS_VIZ_BIND 127.0.0.1 web bind address; set 0.0.0.0 to expose on the network
BESS_VIZ_PORT 8002 web port

Running it

Poller, as a container:

podman build -t bess-viz-poller:latest poller/
podman run -d --name bess-viz-poller --network host \
  -e BESS_OPC_ENDPOINT=opc.tcp://<host>:4840 \
  -v "$PWD/data:/data:Z" \
  bess-viz-poller:latest

Poller, directly (needs asyncua):

python3 -m venv .venv && .venv/bin/pip install asyncua
BESS_VIZ_DATA="$PWD/data/fleet_state.json" .venv/bin/python poller/poll.py

Web (standard library only, no install step):

python3 web/server.py          # http://127.0.0.1:8002

poller/discover.py is a standalone tool that dumps the server's whole namespace tree — useful when pointing this at a plant whose tag layout you don't know yet.

Limitations

Deliberate, and worth stating plainly:

  • No authentication. Binding to 0.0.0.0 exposes it to everyone on the network.
  • No history. If you want trends, that is the historian's job.
  • No control. By design; commanding the plant belongs to the SCADA layer.
  • Anonymous OPC UA. It connects without credentials or encryption, which is a property of the lab it was built against, not a recommendation.

About

Independent OPC UA fleet-state viewer for a BESS digital twin

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages