vetracli
v0.1.7
Published
Single-site commissioning & diagnostics CLI client for Vetra SCADA
Downloads
265
Maintainers
Readme
vetraCLI ⚡
Single-site commissioning & diagnostics CLI client for Vetra SCADA.
vetraCLI runs locally on-site — typically on an edge gateway (e.g. Raspberry Pi, industrial PC) — for field engineers. It authenticates, connects to every device, polls registers in real time, publishes to MQTT, caches readings offline, and syncs to the cloud when connectivity returns.
Install
Global install (recommended for edge deployment)
npm install -g vetracli
vetra setup # interactive first-run provisioning
vetra # start dashboardFrom source
git clone https://github.com/LENL-Vetra/vetraCLI.git
cd vetraCLI
npm install
npm run build
npm install -g .
vetra setupFirst Run
After installing, run the interactive setup wizard:
vetra setupThe wizard walks you through:
- API URL — Vetra backend base URL (e.g.
https://api.lapomikenergy.com) - Product — product scope for login/site filtering (default
vetra) - Login — your Vetra username and password (tokens stored in your profile)
- Site selection — pick the site this gateway manages
- MQTT — broker URL, username, and password
- Poll interval — how often to read registers (ms, default
10000)
All settings are saved to ~/.config/vetra/profile.json. On every subsequent start vetraCLI silently re-authenticates — no credentials re-entry needed.
CLI Commands
# --- First run / provisioning ---
vetra setup # interactive site provisioning wizard
vetra reset # clear the stored profile (re-run setup next time)
# --- Auth ---
vetra auth # show current auth / profile status
vetra auth relogin # re-authenticate with new credentials (keeps site config)
# --- Runtime ---
vetra # default dashboard + polling loop
vetra dashboard # explicit dashboard mode
# --- Utilities ---
vetra --version # installed package version
vetra --help # usage
vetra completion bash # generate shell completions
vetra completion zsh
vetra completion powershell
# Compatibility aliases
vetracliNote:
dashboardrequires a configured profile. If no profile exists, vetraCLI will prompt you to runvetra setupfirst.
Upgrading
npm install -g vetracli@latest
vetra --version # verify new versionYour profile (~/.config/vetra/profile.json) is preserved across upgrades.
Silent Relogin
On every start:
- Profile tokens are loaded and
api.me()is called to validate the session. - If valid → proceed silently. Updated tokens are persisted.
- If expired → exit with a clear message:
Session expired for configured profile.
Run 'vetra auth relogin' to refresh your credentials.No interactive prompts during normal operation — safe for PM2/systemd service use.
Running as a Service (PM2)
npm install -g pm2
pm2 start "vetra dashboard" --name vetra
pm2 save
pm2 startup # generate init script for auto-start on bootSSH into the gateway at any time to check status:
pm2 status
pm2 logs vetraCore Flow
Login → Select Site → Load Devices & Registers
→ Connect Modbus TCP (parallel)
→ Poll Registers
→ Publish to MQTT
→ Cache Locally (zero data loss)
→ Sync to Cloud API
→ Live Terminal Dashboard
→ Diagnose Errors → Suggest FixesArchitecture
src/
├── cli.ts CLI entry point — command routing, profile gate
├── index.ts Main orchestrator — auth, polling loop, dashboard
├── profile.ts Profile CRUD — ~/.config/vetra/profile.json
├── setup.ts Interactive first-run provisioning wizard
├── auth-commands.ts vetra auth / vetra auth relogin
├── version.ts Startup version check (non-blocking)
├── config.ts Runtime config — profile-first, env fallback
├── types.ts TypeScript types mirroring backend models
├── api.ts Axios HTTP client (CRUD + sync endpoints)
├── auth.ts Inquirer-based login + site selection (legacy flow)
├── connections.ts Parallel Modbus TCP connections with retry
├── polling.ts Register reader (HOLDING/INPUT/COIL/DISCRETE, 16/32-bit)
├── mqtt.ts MQTT publisher
├── storage.ts Offline JSON-lines cache with dedup
├── sync.ts Cloud sync engine (best-effort, retry on failure)
├── dashboard.ts Full-screen live terminal dashboard
└── diagnostics.ts Error detection + fix suggestionsProfile File
All persistent configuration is stored in ~/.config/vetra/profile.json:
{
"siteId": "...",
"siteName": "Site Name",
"product": "vetra",
"username": "[email protected]",
"accessToken": "...",
"refreshToken": "...",
"apiUrl": "https://api.lapomikenergy.com",
"mqttUrl": "wss://broker:8084/mqtt",
"mqttUser": "",
"mqttPass": "",
"pollIntervalMs": 10000,
"cliVersion": "0.1.0",
"createdAt": "...",
"updatedAt": "..."
}To reset: vetra reset or delete ~/.config/vetra/profile.json.
Data Flow After Each Poll
Poll Registers → Apply Scale Factor
├─ Publish to MQTT → sites/{siteId}/devices/{deviceId}/registers/{registerId}
├─ Cache Changed Readings → .vetra-data/register_readings.jsonl (dedup)
├─ Aggregate Device Snap → .vetra-data/device_readings.jsonl
└─ Sync to Backend API → (best-effort, cached on failure)
├─ Update Register.value + lastUpdated
├─ Insert RegisterReading docs
├─ Insert DeviceReading docs
└─ Update Device.status → "online"Features
| Feature | Description |
|---|---|
| Profile-based config | All settings persisted in ~/.config/vetra/profile.json — no .env needed |
| Silent relogin | Tokens silently validated on startup — no interactive prompts in service mode |
| Interactive setup | vetra setup wizard provisions everything in one go |
| Version check | Non-blocking startup check for CLI updates from npm |
| Modbus TCP Polling | Connects to all devices in parallel, reads HOLDING/INPUT/COIL/DISCRETE registers with 16/32-bit decode and scale factors |
| MQTT Publishing | Publishes compact device snapshots by default; per-register topics can be enabled for legacy consumers |
| Offline Cache | JSON-lines append-only files with dedup (only stores changed values). Crash-safe, zero data loss |
| Cloud Sync | Flushes cached readings to the backend API. On failure, data stays cached and retries next cycle |
| Live Dashboard | Full-screen terminal UI showing device status, register readings, diagnostics, MQTT status, and sync status |
| Diagnostics | Detects offline devices, faulty connections, register read errors. Suggests specific fixes |
Configuration
Configuration is profile-first. Run vetra setup to configure everything interactively.
Legacy .env Override
Environment variables are still respected as a fallback for advanced use cases:
VETRA_API_URL=https://api.lapomikenergy.com
MQTT_URL=wss://your-mqtt-broker:8084/mqtt
MQTT_USER=
MQTT_PASS=
MQTT_PUBLISH_REGISTER_TOPICS=true
MQTT_PUBLISH_DEVICE_STATE=true
POLL_INTERVAL_MS=10000
DATA_DIR=.vetra-data
VETRA_PRODUCT=vetra
WRITE_CMD_POLL_MS=5000
SYNC_BATCH_SIZE=500Config resolution order:
- Profile (
~/.config/vetra/profile.json) - Existing process environment variables
--env-file <path>orVETRA_ENV_FILE.env.localin CWD.envin CWD~/.config/vetra/.env
Scripts
| Command | Description |
|---|---|
| npm run dev | Run the standard CLI entrypoint via tsx |
| npm run dev:dashboard | Run dashboard mode directly |
| npm run build | Compile TypeScript to dist/ |
| npm start | Run compiled CLI from dist/cli.js |
| npm run smoke:cli | Build and verify standard CLI help/version/subcommand behavior |
| npm run verify:installed | Install the packed tarball into a temp prefix and verify exposed binaries |
| npm run verify:package | Run smoke checks and inspect the npm package tarball |
Distribution Principles
- Uses a dedicated launcher entrypoint so installed binaries support subcommands cleanly.
- Ships only runtime artifacts via the
fileswhitelist inpackage.json. - Exposes stable binaries:
vetraandvetracli. - Builds automatically before packing/publishing via
prepack. - Supports standard
--helpand--versionflags expected from installable CLIs.
Shell Completions
Generate completions directly from the installed CLI:
vetra completion bash
vetra completion zsh
vetra completion powershellExamples:
# bash
vetra completion bash >> ~/.bashrc
# zsh
mkdir -p ~/.zfunc
vetra completion zsh > ~/.zfunc/_vetra
# PowerShell
vetra completion powershell >> $PROFILERelease Workflow
Local release-readiness checks:
npm ci
npm run verify:packageRepository automation:
- CI workflow runs install, build, smoke checks, and
npm pack --dry-runon pushes and pull requests. - Release workflow runs on
v*tags or manual dispatch, verifies the package, uploads the.tgzartifact, and publishes to npm whenNPM_TOKENis configured.
Suggested release flow:
npm version patch
git push --follow-tagsIf publishing to npm, add NPM_TOKEN in the repository secrets first.
Use the release checklist in docs/release-template.md to keep release notes consistent.
MQTT Scaling Guidance
For larger sites, prefer the retained per-device snapshot topic:
sites/{siteId}/devices/{deviceId}/state
Keep per-register topics only for integrations that need them:
sites/{siteId}/devices/{deviceId}/registers/{registerId}
You can disable register-topic fanout with MQTT_PUBLISH_REGISTER_TOPICS=false while keeping snapshot publishing on.
Technology Stack
| Category | Tools | |---|---| | Runtime | Node.js 20+, TypeScript 5.4 | | CLI UI | chalk, ora, inquirer, cli-table3 | | Protocols | modbus-serial, mqtt, axios | | Offline | JSON-lines file cache | | Planned | Ink (React CLI) for Phase 2 |
Data Models
Types in src/types.ts mirror the Vetra backend Mongoose schemas:
- Device.communication —
{ type: "modbus"|"mqtt", modbus?: { connectionType, ipAddress, port, unitId }, mqtt?: { topic, jsonRootKey } } - Register.type —
"HOLDING"|"INPUT"|"COIL"|"DISCRETE" - Register.dataType —
"UINT16"|"INT16"|"UINT32"|"INT32"|"FLOAT32"|"BOOL"|"REAL"(32-bit types read 2 registers) - Register.wordOrder —
"big"|"little"for 32-bit byte swap - RegisterReading —
{ siteId, registerId, address, value, unit, timestamp } - DeviceReading —
{ deviceId, siteId, timestamp, readings: { [name]: { value, unit, address } } }
Use Cases
- ⚡ Commissioning — Verify all devices connect and registers read correctly
- 🔧 Troubleshooting — Diagnose connection failures with specific fix suggestions
- ✅ Validation / QA — Confirm register values match expected ranges
- 📡 Field Diagnostics — Live monitoring at the site with offline data safety
- 🏭 Edge Service — Run unattended on a gateway with PM2/systemd
License
MIT
