import type { Integration, IntegrationData, IntegrationEndpoint } from '../types.js'; import { nutAuthConfigSchema, type NutAuthConfig } from './schema.js'; import { listVariables, listUps } from './client.js'; import { toBatteryGauge, toLoadGauge, toRuntimeCard, toStatusAlert } from './transform.js'; import { wrapError } from '../base.js'; const endpoints: readonly IntegrationEndpoint[] = [ { id: 'battery-status', name: 'Battery Status', description: 'Battery charge percentage', renderer: 'gauge', refreshInterval: 30 }, { id: 'load', name: 'UPS Load', description: 'Current UPS load percentage', renderer: 'gauge', refreshInterval: 30 }, { id: 'runtime', name: 'Runtime Remaining', description: 'Estimated battery runtime', renderer: 'stat-card', refreshInterval: 30 }, { id: 'ups-status', name: 'UPS Status', description: 'Current UPS status with battery alert', renderer: 'alert-banner', refreshInterval: 15 } ]; async function getVarsMap(config: NutAuthConfig): Promise> { const vars = await listVariables(config.nutHost, config.nutPort, config.upsName); return new Map(vars.map((v) => [v.name, v.value])); } export const nutIntegration: Integration = { id: 'nut', name: 'NUT (UPS)', icon: 'battery-charging', description: 'Monitor UPS battery, load, and power status via NUT protocol', authConfigSchema: nutAuthConfigSchema, endpoints, async testConnection(_appUrl: string, config: Record) { try { const parsed = nutAuthConfigSchema.parse(config); const upsList = await listUps(parsed.nutHost, parsed.nutPort); if (upsList.length === 0) { return { success: false, message: 'Connected but no UPS devices found' }; } const found = upsList.includes(parsed.upsName); return found ? { success: true, message: `Connected. UPS "${parsed.upsName}" found.` } : { success: false, message: `Connected but UPS "${parsed.upsName}" not found. Available: ${upsList.join(', ')}` }; } catch (err) { return { success: false, message: err instanceof Error ? err.message : 'Connection failed' }; } }, async fetchData( _appUrl: string, config: Record, endpointId: string ): Promise { try { const parsed = nutAuthConfigSchema.parse(config); const vars = await getVarsMap(parsed); let data; let renderer; switch (endpointId) { case 'battery-status': data = toBatteryGauge(vars); renderer = 'gauge' as const; break; case 'load': data = toLoadGauge(vars); renderer = 'gauge' as const; break; case 'runtime': data = toRuntimeCard(vars); renderer = 'stat-card' as const; break; case 'ups-status': data = toStatusAlert(vars); renderer = 'alert-banner' as const; break; default: throw new Error(`Unknown endpoint: ${endpointId}`); } return { endpointId, renderer, data, fetchedAt: new Date().toISOString() }; } catch (err) { throw wrapError('nut', endpointId, err); } } };