Files
digitaltwin/docs/installation.md
T
2026-08-24 15:35:32 +05:30

290 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Installation and running the demo
Everything needed to get the LINE-1 Digital Twin running on a laptop and present
it, including the copilot and the offline fallback.
If you only want the run-of-show — what to click and what to say — that is
[demo-script.md](demo-script.md) and the
[slide deck](LINE-1-Digital-Twin-Demo.pptx). This file is setup and operation.
---
## 1. Requirements
| | |
|---|---|
| **Node.js** | 20 or newer. Built and tested on **24.4.1**. |
| **npm** | Ships with Node. Tested on **11.13.0**. |
| **Disk** | ~250 MB for `node_modules`, plus models if you use Ollama. |
| **GPU** | Not required. The 3D view is primitives and runs on integrated graphics. |
| **Internet** | Only for `npm install` and the cloud copilot. The demo itself runs fully offline. |
Optional, for the fast local copilot:
| | |
|---|---|
| **Ollama** | Any recent version. Needed only for the **Local** copilot mode. |
Check what you have:
```bash
node -v && npm -v
```
## 2. Install
From the repository root — **not** from `server/` or `web/`. This is an npm
workspaces repo, and one install at the root covers both packages.
```bash
npm install
```
Expect ~240 packages and about 25 seconds. There should be no build step and no
native compilation.
## 3. Configure the copilot (optional)
**The demo works with no configuration at all.** With nothing set, the copilot
falls back to a deterministic rule engine that answers instantly, offline, and
never fails. Skip this section entirely if you just want to see the twin.
Copy the template and edit it:
```bash
cp .env.example .env
```
The server resolves a provider at startup in this order:
1. **OpenRouter** if `OPENROUTER_API_KEY` is set
2. **Ollama** if it answers at `OLLAMA_HOST`
3. **Rule engine** otherwise
```bash
# Cloud — best analysis, slowest and most variable to first token
OPENROUTER_API_KEY=sk-or-v1-...
OPENROUTER_MODEL=stealth/ox-alpha
# Local — fast, needs `ollama serve` running
OLLAMA_HOST=http://127.0.0.1:11434
OLLAMA_MODEL=qwen3.5-4b-32k:latest
# Force the rule engine, for rehearsing the worst case
# COPILOT_PROVIDER=fallback
```
`.env` is gitignored. Keep the key out of commits and out of screen shares.
**You do not have to edit this file to change models.** Once running, the in-app
settings page (**AI ⚙** in the header) lists every model each provider offers and
switches at runtime. See §7.
### If you are using Ollama
```bash
ollama serve
ollama pull qwen3.5-4b-32k
```
One gotcha worth knowing: Ollama commonly sets `OLLAMA_HOST=0.0.0.0` machine-wide.
That is a *bind* address, not a destination — you cannot connect to it. The server
normalizes it to `127.0.0.1` automatically, and the settings page shows both the
configured value and the address actually being dialled.
## 4. Run it
### For the demo (recommended)
```bash
npm run dev
```
Starts the API on **:8787** and the Vite dev server on **:5173**, prefixing each
process's output. One Ctrl+C stops both.
Open **http://localhost:5173**.
You should see, within a couple of seconds:
- Header: **Telemetry live** with a green dot, and a source badge reading `simulated`
- Header: an **AI ⚙** button naming the active provider
- **OEE around 87–90%** — not 100%
- All five stations green, **Alarms: all clear**
- Trend charts already populated with history
The line starts **pre-warmed**: 30 simulated minutes are run before the first
frame is served, so the rolling OEE window is full, the anomaly baselines are
learned, and the charts have history. You are never presenting a dashboard that
just booted.
### Single port, no dev server
For a plant-floor box, a clean rehearsal, or handing someone a link:
```bash
npm run serve
```
Builds the front end and serves everything from **http://localhost:8787** — one
Node process, one port, no Vite. Use `npm run build` and `npm start` separately if
you prefer.
Once `web/dist` exists, the API process serves it too, so `npm run dev` will log
`serving built front end`. That is harmless — but :8787 then shows whatever was
last built, which can be stale. In development always use **:5173**, which is
served live by Vite.
### Other scripts
| Command | What it does |
|---|---|
| `npm run dev` | API + dev server together (the normal way) |
| `npm run dev:server` | API only, on :8787 |
| `npm run dev:web` | Front end only, on :5173 (needs the API running) |
| `npm run build` | Build the front end to `web/dist` |
| `npm start` | Serve API, and `web/dist` if it has been built |
| `npm run serve` | `build` then `start` |
| `npm run simcheck` | Verify the simulation model (no browser needed) |
| `npm run apicheck` | Verify the server API (server must be running) |
## 5. Verify the install
Two suites. Neither needs a browser, and both are worth running once after
install so you know the machine is good.
```bash
npm run simcheck
```
Runs the model headless and asserts what the demo actually claims: signals stay
inside their physical ranges, faults move OEE the right way in a controlled A/B
against an unfaulted line, a packer stoppage propagates upstream as blocking, a
dropped sensor goes stale rather than to zero, setpoint changes are lagged, runs
are reproducible from a seed, and the prediction arrives *before* the threshold is
crossed. Ends with `ALL CHECKS PASSED`.
```bash
npm run apicheck # in a second terminal, with the server running
```
Exercises the WebSocket stream, the control API, fault propagation into the
stream, and the copilot in every provider mode — checking answers are grounded in
real readings rather than generic prose. Ends with `ALL API CHECKS PASSED`.
## 6. Running the demo
The full run-of-show with timings and wording is in
[demo-script.md](demo-script.md). This is the mechanical sequence.
### Ten minutes before
1. `npm run dev`, open **http://localhost:5173**.
2. Confirm the header shows **Telemetry live**.
3. **Pick your copilot and measure it.** Open **AI ⚙**, choose a provider, click
**Test**. Under 4 s to first token is presentable live; 4–12 s means a
noticeable pause; above that, keep it for follow-up questions only. Do this on
the demo machine, on the demo network — cloud latency has measured anywhere
between 2 s and 36 s on consecutive identical calls.
4. Press **Reset** if anyone has been clicking. The line re-warms to ~87% OEE,
all clear, in well under a second.
5. Leave the clock at **1×**. You speed it up during the demo, not before.
6. Rehearse once with **wifi off** so you know what the fallback looks like.
### The sequence
| Step | Action | What to watch |
|---|---|---|
| **1** | Orbit the 3D view. Click **CNC-02**. | Detail charts follow the selection. OEE ~87%. |
| **2** | What-if → drag **Oven setpoint** 305 → 330 °C | Zone 2 lags: 316 °C at 10 s, settles ~30 s. Burner duty spikes 68→85→74%. Drag back to 305. |
| **3** | What-if → **Inject** *CNC-02 bearing degradation*. Set clock **60×**. | Bearing vibration begins climbing toward the dashed Warn 3.5 line. |
| **4** | Wait ~10 simulated minutes | A purple **Trend** card appears: reaches the 4.5 limit in ~40 min of run time, while vibration is still ~2.8. |
| **5** | Click **Explain this** on the bearing alarm, then the **work order** chip | The copilot traces vibration → tool wear → rejects → OEE. It is never told which fault you injected. |
| **6** | **Clear** the fault, click **Tool change**, clock to **20×** | Reject rate falls, OEE recovers. |
| **7** | Copilot selector → **Offline rules**, ask *"Why is OEE down?"* | Same diagnosis in ~40 ms, no model, no network. |
### Resetting between runs
**Reset** in the header clears injected faults, learned baselines and client-side
history, then re-warms the line. Use it between back-to-back demos rather than
restarting the server.
## 7. Switching models at runtime
**AI ⚙** in the header opens the settings page. The dashboard keeps streaming
behind it, so nothing is interrupted.
- **Provider** — Auto / Cloud / Local / Offline rules
- **Model** — every model each provider offers. OpenRouter's catalogue arrives
live with context length and price per million; the Ollama list comes from your
local library with parameter size and quantization. Filter, or type an id.
- **Test** — measures time to first token and grades it
- **Generation** — temperature, max output tokens, reasoning effort
- **Ollama host** — shows the configured value and the address actually dialled
Choices persist to `.copilot-settings.json` (gitignored), so a model picked while
preparing survives a restart. **Reset to defaults** discards that file and falls
back to `.env`. Settings never contain the API key.
Note on reasoning models: reasoning tokens count against the output budget on most
providers, so a reasoning model on a small budget can spend the lot thinking and
return nothing. Keep effort **low** and the budget generous. Ollama thinking
models are sent `think: false` for the same reason.
## 8. Troubleshooting
**`Disconnected` in the header, charts empty.**
The API died. Restart with `npm run dev`; the dashboard reconnects on its own with
backoff and the server comes back pre-warmed. No page reload needed.
**Port already in use.**
Set `PORT` in `.env` for the API. For the dev server, change `server.port` in
`web/vite.config.js` — and its proxy target if you moved the API.
**Copilot returns nothing, or the panel shows a note about an empty answer.**
Expected behaviour, not a break: it fell back to the rule engine and still
answered. Usually a reasoning model exhausting its token budget. Raise max output
tokens or lower reasoning effort in the settings page, or switch to **Local**.
**Copilot says Ollama is unreachable.**
`ollama serve` is not running, or the host is wrong. The settings page shows the
address being dialled — check that first. `0.0.0.0` in your environment is normal
and handled.
**OEE reads 100% and there are no alarms.**
The pre-warm did not run. Check the startup log for `pre-warmed 30 simulated
minutes`. If it is absent, `PREWARM_SEC` has been overridden in
`server/ingest/simulatedSource.js`.
**Server exits immediately with a long message about MQTT or OPC-UA.**
`TELEMETRY_SOURCE` is set to a stub adapter. Set `TELEMETRY_SOURCE=simulated` in
`.env`. The adapters are documented stubs — see [architecture.md](architecture.md).
**3D view is choppy.**
Drop the clock to 20×. The model is fine; the render loop is competing with the
projector. The scene loads no external assets, so this is never a network issue.
**The line is in a strange state.**
Press **Reset**.
## 9. What is where
```
server/
sim/ line.js (part flow, WIP, blocking) · stations.js (physics)
faults.js (injectable profiles) · kpi.js (OEE)
analytics/ trend.js (least squares) · anomaly.js (frozen baselines)
alarms.js (thresholds, latching, predictions)
ingest/ source.js (the seam) · simulatedSource.js
mqttSource.js, opcuaSource.js (documented stubs)
ai/ copilot.js · context.js · rules.js · settings.js
web/src/
three/ Scene.jsx, Station.jsx, Conveyor.jsx
panels/ KPIs, station strip, charts, alarms, what-if, copilot, settings
scripts/ dev.mjs · simcheck.mjs · apicheck.mjs
docs/ demo-script.md · architecture.md · installation.md · the deck
```
Connecting real plant data is [architecture.md](architecture.md) — the ingest
seam, both adapter stubs, and the four things that bite when the data is real.