Architecture¶
WEISS is split into three main services: a React front-end for user interface and widget rendering, a FastAPI back-end for handling OPI contents, authentication and git interaction, and a dedicated EPICS WebSocket bridge. The block diagram below summarizes their interactions:
The next sections have a more detailed breakdown of the internal structure of each service and their interactions.
NGINX¶
NGINX (“engine-x”) serves as a reverse proxy for all incoming traffic. It routes the browser requests to either the frontend, backend API or the EPICS WebSocket internal ports as needed. Behind NGINX all services run under plain HTTP, being the NGINX layer responsible for TLS termination, HTTPS support and routing.
Frontend¶
The frontend is a single-page React application that operates mainly in two modes: editing (available for developer role only, see User Roles), and runtime. In edit mode the user can create and modify widgets on the canvas, while in runtime mode the user can only interact with the widgets but not change their properties or layout.
Both modes share the same core components. When in runtime, however, the connection to the EPICS WebSocket is opened, and widgets are rendered through a separate component through which PV Data traffic is injected.
Backend¶
API¶
The FastAPI back-end exposes three route groups:
Developer routes (
/repos/staging): developer-only endpoints (enforced byrequire_developer) that manage per-user editable copies of OPI repositories. Each registered repository is cloned as a bare Git repository; every developer who opens it gets an isolated git worktree created automatically for their user ID. This means concurrent edits from different users never interfere with each other. Commits, tags, file CRUD, and deployments are all driven through these worktrees via their respective endpoints. For interaction with remote, the Technical Account Token is used. See Git Interaction for more details.Operator routes (
/repos/deployed): read-only endpoints used by the frontend to serve the currently deployed OPI snapshot to “operator” users.Snapshot routes (
/repos/snapshot): provides storage interaction with PV snapshots (saving to disk, fetching values, etc.). These endpoints DO NOT communicate to PVs in any form, i.e., you need to provide the data to be saved, and for restoring, you need to restore it yourself (WEISS frontend does that). This will change as the snapshot feature becomes a standalone service.
Authentication¶
Authentication is based on OAuth 2.0 system, and is available through the /auth route group. At
the moment only authentication via Microsoft Identity Platform is supported
(MSAL), but the
architecture allows for multiple authentication providers to be added in the future as needed.
Note
Auth workflow details to be provided.
EPICS WebSocket bridge (epicsWS)¶
epicsWS is a standalone Python WebSocket service that sits between the frontend and the EPICS
IOCs. The frontend connects to it through WSClient and subscribes to PV names based on the widgets
present on the canvas.
The PVA library used is p4p, see
backend/epicsWS/PVAClient.The CA library used is PyEpics, see
backend/epicsWS/CAClient.
The web socket application and connection manager can be seen in backend/epicsWS/epicsWS. The
concept was based on ORNL PV Web Socket (PVWS).
How it works¶
Based on the default protocol (see Environment Variables) or the
channel prefix of the PV names (e.g pva:// or ca://), the WS chooses the correct provider.
The incoming messages from all origins are parsed through a common interface defined on pvParser
source file. This results in a standard structure in the format of the PVData class, regardless of
the origin of the message.
This class was based on the EPICS Normative Types (with minor modifications for convenience). This way, a known format is always used, and the front-end client only needs to know one data structure for all protocols. Similar to PVWS, extra fields were added for base64 encoding for arrays, improving JSON data traffic. A separate field for enumeration strings for enum/enum-like records was also added.
This service is intentionally isolated from the API: it has no dependency on authentication or repository management and can be deployed and scaled independently.
Further tests on performance and scalability are planned for the near future.