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 functions init and start.
  • 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 bootinit (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 runtimeserver/runtime/devices/redis/index.js::_buildRedisClient constructs a Redis client (no callers inside the repo, but the client is used by device adapters that read/write tags).
  • Project handlingclient/src/app/_services/project.service.ts is 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.ts is imported by 91 modules (Ca = 91). It participates in a circular import cycle with gauges.component and gauge‑property.component, increasing cognitive load and risk of runtime errors.
  • Utility hub_helpers/utils.ts has 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 → n reaches a window.open call that writes temporary files.
  • Network – start → a → o triggers a file‑system open that may be used for downloading device drivers.
  • Database – device adapters call the Redis client and InfluxDB writer (complete in influxdb/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: "*") in server/main.js with an explicit allow list.
  • High – CI workflows do not run tests; add a test step.
  • Medium – Declare least‑privilege GITHUB_TOKEN permissions (.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.js 7.7 MiB) to Git LFS.
  • Medium – Remove generated build output (client/dist/) from VCS.
  • Medium – Set persist-credentials: false on 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.