The Problem
Industrial plants need a low‑cost, web‑based SCADA/HMI that can run on any OS and expose real‑time data from PLCs, MQTT brokers, Modbus devices, etc. Legacy desktop‑only tools force costly licences and OS lock‑in, while custom web stacks are error‑prone and lack a visual editor.
What This Does
FUXA delivers a full‑stack dashboard platform. The backend lives in server/ (Express API, device adapters, Redis/InfluxDB historians) and is started from server/main.js. The frontend is an Angular SPA under client/, compiled to client/dist/. A lightweight Electron wrapper (app/electron/main.js) lets users run the UI locally without a browser. The repository also ships a Node‑RED palette (node-red/node-red-contrib-fuxa) for flow‑based integration.
Key files:
server/api/index.js– defines the REST API, entry functionsinitandstart.server/runtime/devices/redis/index.js::_buildRedisClient– creates the Redis client used by device adapters.client/src/app/_services/project.service.ts– central service that loads/saves projects and propagates changes to the UI.client/src/app/_models/hmi.ts– the hub model imported by 91 other modules (the “hub module”).
How It Is Wired
Execution begins in server/main.js. The function allowCrossDomain (line 368) registers a permissive CORS middleware, then the server imports server/api/index.js.
- API boot –
init(line 35) wires the Express router, registers device runtimes and reaches 280 internal functions. It is called from 25 places, making it a high‑impact node. - Device runtime –
server/runtime/devices/redis/index.js::_buildRedisClientconstructs a Redis client (no callers inside the repo, but the client is used by device adapters that read/write tags). - Project handling –
client/src/app/_services/project.service.tsis imported by 80 other modules (Ca = 80). It loads JSON project files from the server, updates the model (_models/hmi,_models/device) and triggers UI refreshes. Its large import fan‑out and 1258 LOC make it a change‑impact hotspot. - Hub model –
_models/hmi.tsis imported by 91 modules (Ca = 91). It participates in a circular import cycle withgauges.componentandgauge‑property.component, increasing cognitive load and risk of runtime errors. - Utility hub –
_helpers/utils.tshas Ca = 90, Ce = 0 (no outbound imports). It provides low‑level helpers (e.g., file I/O wrappers) that are widely reused; any modification ripples across the codebase.
The internal call graph shows a few “super‑nodes”: functions named each, attr, $ are called from >100 distinct places, indicating heavy reliance on generic utilities (likely lodash‑style helpers).
External effects:
- Filesystem –
init → on → e → nreaches awindow.opencall that writes temporary files. - Network –
start → a → otriggers a file‑system open that may be used for downloading device drivers. - Database – device adapters call the Redis client and InfluxDB writer (
completeininfluxdb/index.js).
Cycles: the import graph contains 18 modules in circular dependencies, the most prominent involving the hub model and gauge components. Breaking these cycles (e.g., extracting shared types into a common module) would lower instability scores and simplify testing.
How To Use It
# Clone the repo
git clone https://github.com/moses-y/FUXA.git
cd FUXA
# Build the Docker image (Dockerfile present)
docker build -t fuxa:local .
# Run the container (exposes UI on 1881)
docker run -d -p 1881:1881 \
-v fuxa_appdata:/usr/src/app/FUXA/server/_appdata \
-v fuxa_db:/usr/src/app/FUXA/server/_db \
-v fuxa_logs:/usr/src/app/FUXA/server/_logs \
fuxa:local
Alternatively, for local development:
# Backend
cd server
npm ci
npm start # runs server/main.js
# Frontend
cd ../client
npm ci
npm run build # produces client/dist/
npm run serve # serves Angular app
Configuration files are under server/ (e.g., server/_config.json) and client/ (Angular environment files). No secret keys are committed; the README points to environment variables for database credentials.
Real‑World Use
A manufacturing line installs a Raspberry Pi running the Docker image. The Pi connects to a Modbus TCP PLC, stores tag history in InfluxDB, and the UI is accessed from a browser at http://<pi_ip>:1881. Engineers use the web editor to drag SVG gauges onto a dashboard, then export the project JSON for version control.
Code Health & Issues
- High – Pin GitHub Actions to commit SHAs (
.github/workflows/*). - High – Add a lockfile for
node-red/node-red-contrib-fuxa/package.json. - High – Replace wildcard CORS (
origin: "*") inserver/main.jswith an explicit allow list. - High – CI workflows do not run tests; add a test step.
- Medium – Declare least‑privilege
GITHUB_TOKENpermissions (.github/workflows/docker_image.yml). - Medium – Pin Docker base images by digest (
Dockerfile). - Medium – Add a dependency‑vulnerability scan to CI.
- Medium – Move large binaries (e.g.,
client/dist/main.161a5989ea50187f.js7.7 MiB) to Git LFS. - Medium – Remove generated build output (
client/dist/) from VCS. - Medium – Set
persist-credentials: falseon checkout (.github/workflows/electron_latest.yml).
Additional static findings: 29 deep‑nesting spots, 11 import cycles, 6 oversized files (>1 k LOC), and numerous empty catch {} blocks that silently swallow errors.
The Bottom Line
FUXA provides a functional, Docker‑ready SCADA/HMI stack with a visual editor and broad protocol support, but the codebase suffers from high coupling (hub modules, import cycles) and several security‑hardening gaps. It is suitable for teams that can allocate effort to refactor the core services and tighten CI/CD practices before using it in production.