# SCADA Device Layout Tool Visual layout editor for designing conveyor system SCADA views. Generates Ignition Perspective views with full tag bindings, deployable directly to an Ignition gateway. Built with SvelteKit + Svelte 5 + TypeScript + HTML5 Canvas. ## What It Does - Drag-and-drop placement of conveyor system devices (VFDs, photoeyes, EPCs, sensors, controls, etc.) onto a canvas - Trace PDF blueprints as background reference while placing devices - Assign device IDs from Excel manifests to placed symbols - Export production-ready Ignition Perspective `view.json` with tag bindings (color/state/priority), pan/zoom controls, tooltips, and alarm filters - Deploy directly to the Ignition gateway filesystem with automatic project rescan ## Data Sources ### Excel Device Manifests `svelte-app/static/projectes/{PROJECT}/excel/*.xlsx` Each file represents one MCM (Module Control Module) with device IO data. Parsed at build time (Vite plugin) into `devices-manifest.json` — device IDs mapped to symbol types, organized by MCM. ### PDF Blueprints `svelte-app/static/projectes/{PROJECT}/pdf/*.pdf` Conveyor layout drawings rendered as canvas background for accurate device tracing. ### SVG Symbols `svelte-app/static/symbols/*.svg` Vector graphics for each device type. Rendered programmatically on canvas for consistent stroke width at any size. ### Ignition Tag Tree Tag paths follow the Ignition tag provider hierarchy: ``` System/{MCM}/ VFD/APF/ - Variable Frequency Drives Station/Emergency_Pull_Cord/ - EPCs Station/Start/ - Start Buttons (S) Station/Start_Stop/ - Start/Stop Buttons (SS) Station/Jam_Reset/ - Jam Reset Buttons (JR) Station/Jam_Reset_Chute_Bank/ - Chute Enable Buttons Sensor/Tracking/ - Tracking Photoeyes (TPE) Sensor/Laser/ - Laser Photoeyes (LPE) Sensor/Jam/ - Jam Photoeyes (JPE) Sensor/Full/ - Full Photoeyes (FPE) Sensor/Pressure/ - Pressure Sensors (PS) Network_Node/FIO/ - Field I/O Modules (FIOM) Network_Node/HUB/ - Hub Modules (FIOH) Network_Node/SIO/ - Serial I/O Modules Network_Node/DPM/ - Distribution Power Modules Beacon/ - Beacon Lights (BCN) Solenoid/ - Solenoid Valves (SOL) Diverter/ - Diverter Limit Switches PDP/ - Power Distribution Panels Chute/Conveyance/ - Chute Conveyors Tipper/ - Tipper Conveyors Extendo/ - Extendo Conveyors ``` ## How It Works ### 1. Project Setup Select a project and MCM from the toolbar. Device manifest and PDF blueprint load automatically. ### 2. Layout Design - Drag symbols from the palette onto the canvas - Resize conveyors, spurs, and curves by dragging handles - Rotate (R), mirror (M), snap to grid - Shift+drag constrains to horizontal/vertical - Mouse wheel to zoom, middle-click to pan ### 3. Device Assignment - Drag device IDs from the right dock onto placed symbols - IDs match by conveyance family (conveyor IDs work on spurs, curves, inductions, extendos) - Labels render inside conveyance shapes as bold text (parsed: `UL17_22_VFD` -> `UL / 17-22`) ### 4. Export Options | Button | Output | Description | |--------|--------|-------------| | **SVG** | `{MCM}_Detailed_View.svg` | Standard SVG with shapes, labels, embedded layout data | | **JSON** | `{MCM}_layout.json` | Layout data for backup/restore | | **SCADA** | `{MCM}_Detailed_View.json` | Ignition `ia.shapes.svg` component JSON | | **Deploy** | Writes to Ignition | `view.json` + `resource.json` to gateway project directory | ### 5. Ignition View Structure Generated `view.json` includes: - **Pan/zoom container** — mouse wheel zoom, pointer-move panning, double-click reset - **SVG component** — all device shapes with per-element tag bindings: - `color` — indirect tag binding to `[{fc}_SCADA_TAG_PROVIDER]{tagpath}/Color` with 21-color state map - `state` — indirect tag binding to `[{fc}_SCADA_TAG_PROVIDER]{tagpath}/State` with 35-state map - `priority` — indirect tag binding to `[{fc}_SCADA_TAG_PROVIDER]{tagpath}/Priority` (5 levels) - `fill.paint` / `stroke.paint` — dynamic coloring based on device type - `style.display` — alarm-based visibility filters (`show_fio`, `show_pes`, `show_beacons`, etc.) - **Markdown tooltip** — hover tooltips with device state/priority, glow effects on active elements - **Zoom controls** — reset, zoom in/out, percentage dropdown - **Message handler** — `focusDevice` for external navigation ### Device-Specific Bindings | Device Type | Fill Binding | Notes | |-------------|-------------|-------| | Conveyor/Chute/Spur/Induction | `elements[0].fill.paint` + text contrast | Background + text color | | DPM | `elements[0].fill.paint` only | First triangle path | | MCM | `elements[1].fill.paint` only | Second triangle path | | EPC | `elements[0].stroke.paint` + `elements[1].elements[1].fill.paint` | Polyline stroke + icon inner | | Buttons (JR/S/SS) | Text `fill.paint` only | Background keeps static color | | Photoeye/FIO/Beacon/etc. | `elements[0].fill.paint` | Standard fill | ## Setup & Run ```sh cd svelte-app npm install npm run dev # Dev server at http://localhost:5173 ``` ## Gateway Integration ### Deploy Target Files are written to: ``` C:/Program Files/Inductive Automation/Ignition/data/projects/{PROJECT}/ com.inductiveautomation.perspective/views/DetailedView/{MCM}/ view.json # Full Perspective view with bindings resource.json # Resource metadata with SHA-256 signature ``` ### Automatic Project Rescan A gateway timer script (5s interval) watches for `.deploy-pending` trigger files and calls `IgnitionGateway.get().getProjectManager().requestScan()` so the Designer picks up new views without a gateway restart. Gateway Timer Script setup: ```python import os basePath = "C:/Program Files/Inductive Automation/Ignition/data/projects" projects = ["CDW5_SCADA"] for proj in projects: viewsDir = os.path.join(basePath, proj, "com.inductiveautomation.perspective", "views") if not os.path.exists(viewsDir): continue for root, dirs, files in os.walk(viewsDir): if ".deploy-pending" in files: trigger = os.path.join(root, ".deploy-pending") os.remove(trigger) from com.inductiveautomation.ignition.gateway import IgnitionGateway IgnitionGateway.get().getProjectManager().requestScan() system.util.getLogger("SCADADeploy").info("Deployed view: " + root) ``` ## Project Structure ``` scada_device_layout/ svelte-app/ src/ lib/ canvas/ renderer.ts # Canvas draw loop, symbol rendering interactions.ts # Mouse/keyboard handlers, drag-and-drop hit-testing.ts # Shape-aware click detection collision.ts # Spacing violation detection render-theme.ts # Visual constants (colors, sizes) grid-snap.ts # Grid snapping distance.ts # Geometry helpers geometry.ts # Oriented box math stores/ layout.svelte.ts # Central state (symbols, selection, settings) export.ts # SVG/JSON/SCADA export, Ignition deploy ignition-view.ts # Full view.json generator with all bindings symbols.ts # Symbol definitions, type checks, image cache symbol-config.ts # Geometry constants (EPC, induction, photoeye, etc.) label-utils.ts # Label parsing (UL17_22_VFD -> UL / 17-22) serialization.ts # Save/load with size migration pdf.ts # PDF background rendering projects.ts # Project/MCM discovery types.ts # TypeScript interfaces components/ Canvas.svelte # Main canvas + PDF + context menu Toolbar.svelte # Left sidebar (project, settings, palette, Ignition deploy) Palette.svelte # Symbol picker with groups DeviceDock.svelte # Right sidebar (device ID assignment) static/ symbols/ # SVG files for each device type projectes/ # Project data (Excel, PDF, manifests) vite.config.ts # Vite plugins: manifest gen, Excel parser, deploy endpoint ``` ## Device Classification (from Excel) | Suffix | Symbol | Tag Path | |--------|--------|----------| | VFD | Conveyor | VFD/APF | | EPC | EPC | Station/Emergency_Pull_Cord | | TPE | Photoeye | Sensor/Tracking | | LPE | Photoeye | Sensor/Laser | | JPE | Photoeye | Sensor/Jam | | FPE | Photoeye | Sensor/Full | | PS | Pressure Sensor | Sensor/Pressure | | BDS, TS | Photoeye | Sensor/Tracking | | JR_PB | Jam Reset | Station/Jam_Reset | | S_PB | Start | Station/Start | | SS_SPB/STPB | Start Stop | Station/Start_Stop | | EN_PB | Chute Enable | Station/Jam_Reset_Chute_Bank | | BCN | Beacon | Beacon | | SOL | Solenoid | Solenoid | | DIV_LS | Diverter | Diverter | | FIOM | FIO/SIO/FIOH | Network_Node/FIO | | FIOH | FIO/SIO/FIOH | Network_Node/HUB | | SIO | FIO/SIO/FIOH | Network_Node/SIO | | DPM | DPM | Network_Node/DPM | | PDP | PDP | PDP | Note: `_PB`/`_SPB`/`_STPB` suffixes are stripped from tag paths to match PLC naming. Skipped: ENSH/ENW (encoders), VFD_DISC (disconnect), _LT (lights), EPC 2nd channel, ESTOP, SCALE, STO, PRX, LRPE.