# Phase 3: NUT/UPS Integration **Status:** ⬜ Not Started **Parent plan:** [PLAN.md](./PLAN.md) **Domain:** backend ## Objective Implement the NUT/UPS integration using direct TCP protocol to communicate with NUT servers. This is the only non-HTTP integration — it connects directly to the NUT daemon on port 3493. ## Tasks - [ ] Task 1: Create `src/lib/server/integrations/nut/schema.ts` — Zod schemas for auth config (`{ nutHost: string, nutPort: number, upsName: string }`) and endpoint responses. - [ ] Task 2: Create `src/lib/server/integrations/nut/client.ts` — NUT TCP protocol client using Node `net` module. Implement commands: `LIST UPS`, `LIST VAR `, `GET VAR `. Parse NUT protocol responses. Handle connection timeout and cleanup. - [ ] Task 3: Create `src/lib/server/integrations/nut/transform.ts` — Transform raw NUT variables to widget-ready data. Map: `battery.charge` → gauge %, `ups.load` → gauge %, `battery.runtime` → stat-card (formatted as Xh Ym), `ups.status` → alert level (OL=ok, OB=warning, LB=critical). - [ ] Task 4: Create `src/lib/server/integrations/nut/index.ts` — Integration implementation. Register with registry. Endpoints: `battery-status` (gauge), `load` (gauge), `runtime` (stat-card), `ups-status` (alert-banner). testConnection: attempt TCP connect + `LIST UPS`. - [ ] Task 5: Register NUT integration in `src/lib/server/integrations/registry.ts`. - [ ] Task 6: Create API route for NUT alerts `src/routes/api/integrations/alerts/+server.ts` — `GET` returns active critical alerts across all apps with integrations (UPS on battery, etc.). Used by IntegrationAlertOverlay. ## Files to Modify/Create - `src/lib/server/integrations/nut/schema.ts` — new - `src/lib/server/integrations/nut/client.ts` — new - `src/lib/server/integrations/nut/transform.ts` — new - `src/lib/server/integrations/nut/index.ts` — new - `src/lib/server/integrations/registry.ts` — modify: register NUT - `src/routes/api/integrations/alerts/+server.ts` — new ## Acceptance Criteria - NUT client connects to NUT server via TCP and retrieves UPS variables - Battery charge displayed as percentage gauge - Load displayed as percentage gauge - Runtime formatted as human-readable time - Status correctly maps OL/OB/LB to alert levels - Alert banner fires when status is OB or LB - Connection test validates TCP connectivity - Handles connection timeouts and refused connections gracefully ## Notes - NUT protocol is text-based over TCP: send `GET VAR \n`, receive `VAR ""\n` - Default port: 3493 - Does NOT use app.url — uses nutHost/nutPort/upsName from extraConfig - TCP connections should be short-lived (connect, query, disconnect) — don't keep persistent connections - Common UPS variables: battery.charge, battery.runtime, ups.load, ups.status, input.voltage, output.voltage ## Review Checklist - [ ] All tasks completed - [ ] TCP client handles timeouts and errors - [ ] No resource leaks (sockets always closed) - [ ] Code follows project conventions ## Handoff to Next Phase