# Functional Specification — uopi ## 1. Purpose uopi is a web-based HMI (Human-Machine Interface) for monitoring and controlling industrial/scientific systems, primarily EPICS-based control systems. It runs as a single server process and is accessed entirely through a web browser, making it suitable for SSH-tunnelled remote access. --- ## 2. Users and Roles | Role | Description | |------|-------------| | Operator | Uses interfaces in View mode; can interact with controls but cannot edit layouts | | Engineer | Creates and edits interfaces in Edit mode; manages signal lists | | Administrator | Manages server configuration, data sources, and saved interfaces | In the initial version all users share the same access level. Role-based access control is deferred to a future release. --- ## 3. System Modes ### 3.1 View Mode (default) The default mode when opening the application. **Interface list pane (left, collapsible)** - Displays all interfaces saved on the server, grouped into a tree by folder. - Right-click on an interface: options to open in Edit mode or clone it. - "New interface" button opens Edit mode with a blank canvas. - "Import" option loads an interface from a local XML file. **HMI canvas (center)** - Renders the selected interface as a live, interactive panel. - Widgets display real-time data; controls (set-value, buttons) are active. - No drag, resize, or layout operations are possible in this mode. - Right-clicking any widget opens a context menu: - **Signal info** — floating window showing DS name, type, unit, range, current value and timestamp. - **Copy signal name** — copies the signal identifier to the clipboard. - **Export data to CSV** — downloads buffered/historical data for the signal(s) used by the widget. **Top toolbar** - Show/hide interface list pane. - Time selector: navigate to a past timestamp (enabled only when the server has archive access for all signals on the canvas). - "Live" button: return to real-time data after historical navigation. ### 3.2 Edit Mode Activated via the "New interface" button or by right-clicking an existing interface. **Signal tree pane (left, resizable and collapsible)** - Shows all signals known to each connected data source. - Sources are shown as top-level nodes; signals are nested within. - User can add custom entries: - For EPICS: manually enter a PV name. - For Synthetic: define a new synthetic signal (see §5.2). - User can load a CSV file with columns `NAME, DataSource, DS_PARAMETERS` to import a batch of signals. - Filter/search box to narrow the list. **Widget canvas (center)** - Free-form canvas where widgets can be placed at arbitrary pixel positions. - Background grid with optional snap-to-grid. **Properties pane (right, collapsible)** - Appears when one or more widgets are selected. - Displays and edits all options for the selected widget (see §4). **Top toolbar** - Show/hide signal pane. - Show/hide properties pane. - Undo / Redo (also Ctrl+Z / Ctrl+Shift+Z). - Save interface to server. - Load interface from server. - Export interface to local XML file. - Import interface from local XML file. - "Add text" tool — inserts a static text label. - "Add image" tool — inserts a static image (uploaded to server or embedded as base64). - "Add link" tool — inserts a button that opens another interface. --- ## 4. Widgets ### 4.1 Creating Widgets Drag a signal from the signal tree and drop it onto the canvas. A picker appears showing all widget types compatible with the signal's data type (iconised). The user selects one and the widget is placed at the drop location with default size. ### 4.2 Selecting Widgets - Single click: select one widget (deselects others). - Ctrl+click: add/remove a widget from the current selection. - Click-drag on empty canvas area: rubber-band area select. When a widget is selected, a bounding box appears with: - 8 resize handles (corners + midpoints). - A delete button (×) in the top-right corner. - The widget can be moved by dragging its body. ### 4.3 Multi-selection Operations When multiple widgets are selected: - Drag any selected widget to move them all together. - Del key deletes all selected widgets. - An align/distribute toolbar appears above the canvas with: - Align left / center horizontal / right. - Align top / center vertical / bottom. - Distribute evenly — by center spacing (horizontal/vertical). - Distribute evenly — by gap size (horizontal/vertical). ### 4.4 Widget Catalogue | Widget | Compatible signal types | Description | |--------|-------------------------|-------------| | Text view | any scalar | Displays `name: value unit` | | Gauge | numeric scalar | Circular or arc gauge with configurable range | | Vertical bar | numeric scalar | Vertical level indicator | | Horizontal bar | numeric scalar | Horizontal level indicator | | Set value | numeric or string, writable | Shows `name: [input field] current_value unit` + Set button | | LED | boolean / numeric | Coloured indicator with configurable condition and label | | Multi-LED | integer (bitset) | One LED per bit with individual labels and conditions | | Button | writable | Sends a fixed value or command on click | | Plot | numeric scalar or array | Multi-signal plot; sub-types below | | Text label | — | Static text annotation | | Image | — | Static image | | Link | — | Button navigating to another interface | **Plot sub-types:** | Sub-type | Signal requirement | |----------|--------------------| | Time series | numeric scalar(s) | | FFT | 1-D numeric array | | Waterfall | 1-D numeric array (repeated) | | Histogram | numeric scalar(s) | | Bar chart | numeric scalar(s) | | Logic analyser | boolean / integer (bitset) | ### 4.5 Widget Properties (Properties Pane) Common to all: - Label text, font size, text colour. - Position (X, Y) and size (W, H) — editable numerically. - Data source and signal name (read-only after creation; reassignable via drag). Per type: - **Gauge / Bar**: min value, max value, alert thresholds with colours, unit label. - **LED / Multi-LED**: condition expression (e.g. `value > 0`), colours for true/false states. - **Plot**: plot sub-type selector, Y-axis range (auto or manual), time window duration, legend position, colour per signal, line style. - **Set value**: input type (numeric / string / enum), confirmation prompt toggle. - **Link**: target interface name. --- ## 5. Data Sources ### 5.1 EPICS - Connects to an EPICS environment via Channel Access (CA) or PVAccess (PVA). - On connect, retrieves full metadata from the PV name: data type, engineering units, display range (DRVL/DRVH, LOPR/HOPR), alarm limits, enum strings (for mbbi/mbbo records), read/write mode, acquisition mode. - Prefers monitor/subscription over polling. Falls back to polling only when monitors are unavailable. - Attempts to enumerate available PV names from the IOC (e.g. via PV lists or Channel Finder). Unknown PVs can still be manually added by the user. - When an EPICS Archive Appliance or Channel Archiver is configured, the server can satisfy historical data requests. ### 5.2 Synthetic A signal defined by composing one or more input signals (from any data source) through a chain of processing functions. **Built-in processing functions (non-exhaustive):** - Arithmetic: gain, offset, add, subtract, multiply, divide. - Signal processing: moving average (N samples or time window), RMS, bandpass filter (IIR/FIR), lowpass / highpass filter, derivative, integral. - FFT, inverse FFT. - Peak detection, threshold crossing. - Custom formula: inline expression (`a * sin(b) + c`). - Lua script block: arbitrary Lua code with access to input values and state. **User workflow:** 1. Click "New synthetic signal" in the signal tree. 2. Name the signal and choose input signals. 3. Build a processing pipeline by chaining function blocks (UI similar to a node graph or an ordered list). 4. Optionally write a Lua snippet for custom logic. 5. The synthetic signal appears in the tree and can be used like any other signal. --- ## 6. Interface Persistence - Interfaces are saved to the server in XML format and are available to all connected clients. - Export/Import allows local file exchange of XML files. - The XML schema records: widget type, position, size, signal bindings, and all property values. --- ## 7. Historical Data Navigation When the server has archive access for all signals on the current canvas: - The top toolbar shows a date/time picker. - Selecting a past time replays data from the archive into all widgets. - The "Live" button resumes real-time streaming. - Widgets that support time-axis (plots) show the historical range; point-value widgets show the value at the selected time. --- ## 8. Non-functional Requirements | Requirement | Target | |-------------|--------| | Server binary | Single statically-linked executable; no runtime dependencies | | Target platform | Linux x86-64; also aarch64 optional | | Minimum server OS | RHEL/CentOS 7 (glibc 2.17) or equivalent | | Concurrent clients | ≥ 20 simultaneous browser clients | | Data fan-out latency | < 5 ms added latency vs. raw EPICS update rate | | Frontend responsiveness | 60 fps canvas rendering during live updates | | Screen DPI | Frontend adapts to device pixel ratio |