Developers/Foundations
Architecture
Layers, modules and engine boundaries for contributing to or extending abSCADA.
2 min read
abSCADA is a modular monolith in Python. One application, but with a core that knows nothing about the UI: project, runtime, alarms and storage all work without Qt.
Layers
Studio (Qt) ──► Project (load & validate) ◄──► JSON files
│
└──► RuntimeWindow ──► Runtime (sample store)
├── Write queue
├── Worker per connection ──► Connector ──► S7 / Modbus
├── OperationsService ──► SQLite (alarms, loggers)
└── ScriptService ──► isolated Python process
Main modules
| Module | Responsibility | Does not know |
|---|---|---|
project.py |
Loading, validation, structures and faceplates | Qt, sockets |
connectors.py |
Connector contract, registry and S7 |
Widgets |
protocol_definition.py |
Connection and binding schemas | Qt, network |
modbus.py |
Modbus TCP client | Screens |
runtime.py |
Values, quality, queue, acquisition | Graphic editing |
alarms.py |
Alarm state machine | Transport |
storage.py |
SQLite, queries, retention | PLC clients |
scripting.py |
Script and task coordinator | Widgets |
graphics.py |
Canvas and drawing primitives | PLC clients |
ui.py |
Studio | Live readings |
runtime_window.py |
Operator window | Editable state |
Principles
- Studio never consumes samples. Runtime works on a deep copy of the project.
- Writes are commands. They are validated before queuing and never replayed after reconnecting.
- One worker per connection. A slow device never delays another.
- A single SQLite writer. PLC workers only hand samples to a queue.
- Open formats. No Qt objects or opaque binaries are serialised.
Sample model
Sample(value=72.4, quality="good", timestamp=1759651200.123, error=None)
quality is good, uncertain or bad. timestamp is the update time in the runtime, not a PLC timestamp.
Known limits
Reads inside a connection are individual. Thousands of variables will need grouped reads, metrics and stale quality. Maximum capacity has not been measured yet.