fix(cli): resolve process hang and improve output consistency
- Add process.stdin.destroy() after rl.close() in all interactive commands to properly release stdin and allow process to exit cleanly - Replace raw console.log with logger methods throughout CLI handlers - Convert manual box drawing to logger.logBox() in daemon.ts - Standardize menu formatting with logger.info() and logger.dim() - Improve migration output to only show when migrations actually run Fixes issue where process would not exit after "Setup complete!" message due to stdin keeping the event loop alive.
This commit is contained in:
@@ -192,6 +192,7 @@ export class GroupHandler {
|
|||||||
logger.log('\nGroup setup complete!');
|
logger.log('\nGroup setup complete!');
|
||||||
} finally {
|
} finally {
|
||||||
rl.close();
|
rl.close();
|
||||||
|
process.stdin.destroy();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Add group error: ${error instanceof Error ? error.message : String(error)}`);
|
logger.error(`Add group error: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
@@ -309,6 +310,7 @@ export class GroupHandler {
|
|||||||
logger.log('\nGroup edit complete!');
|
logger.log('\nGroup edit complete!');
|
||||||
} finally {
|
} finally {
|
||||||
rl.close();
|
rl.close();
|
||||||
|
process.stdin.destroy();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Edit group error: ${error instanceof Error ? error.message : String(error)}`);
|
logger.error(`Edit group error: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
@@ -366,6 +368,7 @@ export class GroupHandler {
|
|||||||
});
|
});
|
||||||
|
|
||||||
rl.close();
|
rl.close();
|
||||||
|
process.stdin.destroy();
|
||||||
|
|
||||||
if (confirm !== 'y' && confirm !== 'yes') {
|
if (confirm !== 'y' && confirm !== 'yes') {
|
||||||
logger.log('Deletion cancelled.');
|
logger.log('Deletion cancelled.');
|
||||||
|
@@ -213,9 +213,11 @@ export class ServiceHandler {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('\nNUPST Uninstaller');
|
logger.log('');
|
||||||
console.log('===============');
|
logger.highlight('NUPST Uninstaller');
|
||||||
console.log('This will completely remove NUPST from your system.\n');
|
logger.dim('===============');
|
||||||
|
logger.log('This will completely remove NUPST from your system.');
|
||||||
|
logger.log('');
|
||||||
|
|
||||||
// Ask about removing configuration
|
// Ask about removing configuration
|
||||||
const removeConfig = await prompt(
|
const removeConfig = await prompt(
|
||||||
@@ -251,17 +253,20 @@ export class ServiceHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!uninstallScriptPath) {
|
if (!uninstallScriptPath) {
|
||||||
console.error('Could not locate uninstall.sh script. Aborting uninstall.');
|
logger.error('Could not locate uninstall.sh script. Aborting uninstall.');
|
||||||
rl.close();
|
rl.close();
|
||||||
|
process.stdin.destroy();
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close readline before executing script
|
// Close readline before executing script
|
||||||
rl.close();
|
rl.close();
|
||||||
|
process.stdin.destroy();
|
||||||
|
|
||||||
// Execute uninstall.sh with the appropriate option
|
// Execute uninstall.sh with the appropriate option
|
||||||
console.log(`\nRunning uninstaller from ${uninstallScriptPath}...`);
|
logger.log('');
|
||||||
|
logger.log(`Running uninstaller from ${uninstallScriptPath}...`);
|
||||||
|
|
||||||
// Pass the configuration removal option as an environment variable
|
// Pass the configuration removal option as an environment variable
|
||||||
const env = {
|
const env = {
|
||||||
@@ -277,7 +282,7 @@ export class ServiceHandler {
|
|||||||
stdio: 'inherit', // Show output in the terminal
|
stdio: 'inherit', // Show output in the terminal
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Uninstall failed: ${error instanceof Error ? error.message : String(error)}`);
|
logger.error(`Uninstall failed: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -47,6 +47,7 @@ export class UpsHandler {
|
|||||||
await this.runAddProcess(prompt);
|
await this.runAddProcess(prompt);
|
||||||
} finally {
|
} finally {
|
||||||
rl.close();
|
rl.close();
|
||||||
|
process.stdin.destroy();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Add UPS error: ${error instanceof Error ? error.message : String(error)}`);
|
logger.error(`Add UPS error: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
@@ -178,6 +179,7 @@ export class UpsHandler {
|
|||||||
await this.runEditProcess(upsId, prompt);
|
await this.runEditProcess(upsId, prompt);
|
||||||
} finally {
|
} finally {
|
||||||
rl.close();
|
rl.close();
|
||||||
|
process.stdin.destroy();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Edit UPS error: ${error instanceof Error ? error.message : String(error)}`);
|
logger.error(`Edit UPS error: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
@@ -344,6 +346,7 @@ export class UpsHandler {
|
|||||||
});
|
});
|
||||||
|
|
||||||
rl.close();
|
rl.close();
|
||||||
|
process.stdin.destroy();
|
||||||
|
|
||||||
if (confirm !== 'y' && confirm !== 'yes') {
|
if (confirm !== 'y' && confirm !== 'yes') {
|
||||||
logger.log('Deletion cancelled.');
|
logger.log('Deletion cancelled.');
|
||||||
@@ -667,10 +670,11 @@ export class UpsHandler {
|
|||||||
|
|
||||||
// SNMP Version
|
// SNMP Version
|
||||||
const defaultVersion = snmpConfig.version || 1;
|
const defaultVersion = snmpConfig.version || 1;
|
||||||
console.log('\nSNMP Version:');
|
logger.log('');
|
||||||
console.log(' 1) SNMPv1');
|
logger.info('SNMP Version:');
|
||||||
console.log(' 2) SNMPv2c');
|
logger.dim(' 1) SNMPv1');
|
||||||
console.log(' 3) SNMPv3 (with security features)');
|
logger.dim(' 2) SNMPv2c');
|
||||||
|
logger.dim(' 3) SNMPv3 (with security features)');
|
||||||
const versionInput = await prompt(`Select SNMP version [${defaultVersion}]: `);
|
const versionInput = await prompt(`Select SNMP version [${defaultVersion}]: `);
|
||||||
const version = parseInt(versionInput, 10);
|
const version = parseInt(versionInput, 10);
|
||||||
snmpConfig.version = versionInput.trim() && (version === 1 || version === 2 || version === 3)
|
snmpConfig.version = versionInput.trim() && (version === 1 || version === 2 || version === 3)
|
||||||
@@ -697,13 +701,15 @@ export class UpsHandler {
|
|||||||
snmpConfig: any,
|
snmpConfig: any,
|
||||||
prompt: (question: string) => Promise<string>,
|
prompt: (question: string) => Promise<string>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
console.log('\nSNMPv3 Security Settings:');
|
logger.log('');
|
||||||
|
logger.info('SNMPv3 Security Settings:');
|
||||||
|
|
||||||
// Security Level
|
// Security Level
|
||||||
console.log('\nSecurity Level:');
|
logger.log('');
|
||||||
console.log(' 1) noAuthNoPriv (No Authentication, No Privacy)');
|
logger.info('Security Level:');
|
||||||
console.log(' 2) authNoPriv (Authentication, No Privacy)');
|
logger.dim(' 1) noAuthNoPriv (No Authentication, No Privacy)');
|
||||||
console.log(' 3) authPriv (Authentication and Privacy)');
|
logger.dim(' 2) authNoPriv (Authentication, No Privacy)');
|
||||||
|
logger.dim(' 3) authPriv (Authentication and Privacy)');
|
||||||
const defaultSecLevel = snmpConfig.securityLevel
|
const defaultSecLevel = snmpConfig.securityLevel
|
||||||
? snmpConfig.securityLevel === 'noAuthNoPriv'
|
? snmpConfig.securityLevel === 'noAuthNoPriv'
|
||||||
? 1
|
? 1
|
||||||
@@ -752,8 +758,9 @@ export class UpsHandler {
|
|||||||
|
|
||||||
// Allow customizing the timeout value
|
// Allow customizing the timeout value
|
||||||
const defaultTimeout = snmpConfig.timeout / 1000; // Convert from ms to seconds for display
|
const defaultTimeout = snmpConfig.timeout / 1000; // Convert from ms to seconds for display
|
||||||
console.log(
|
logger.log('');
|
||||||
'\nSNMPv3 operations with authentication and privacy may require longer timeouts.',
|
logger.info(
|
||||||
|
'SNMPv3 operations with authentication and privacy may require longer timeouts.',
|
||||||
);
|
);
|
||||||
const timeoutInput = await prompt(`SNMP Timeout in seconds [${defaultTimeout}]: `);
|
const timeoutInput = await prompt(`SNMP Timeout in seconds [${defaultTimeout}]: `);
|
||||||
const timeout = parseInt(timeoutInput, 10);
|
const timeout = parseInt(timeoutInput, 10);
|
||||||
@@ -773,9 +780,10 @@ export class UpsHandler {
|
|||||||
prompt: (question: string) => Promise<string>,
|
prompt: (question: string) => Promise<string>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// Authentication protocol
|
// Authentication protocol
|
||||||
console.log('\nAuthentication Protocol:');
|
logger.log('');
|
||||||
console.log(' 1) MD5');
|
logger.info('Authentication Protocol:');
|
||||||
console.log(' 2) SHA');
|
logger.dim(' 1) MD5');
|
||||||
|
logger.dim(' 2) SHA');
|
||||||
const defaultAuthProtocol = snmpConfig.authProtocol === 'SHA' ? 2 : 1;
|
const defaultAuthProtocol = snmpConfig.authProtocol === 'SHA' ? 2 : 1;
|
||||||
const authProtocolInput = await prompt(
|
const authProtocolInput = await prompt(
|
||||||
`Select Authentication Protocol [${defaultAuthProtocol}]: `,
|
`Select Authentication Protocol [${defaultAuthProtocol}]: `,
|
||||||
@@ -799,9 +807,10 @@ export class UpsHandler {
|
|||||||
prompt: (question: string) => Promise<string>,
|
prompt: (question: string) => Promise<string>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// Privacy protocol
|
// Privacy protocol
|
||||||
console.log('\nPrivacy Protocol:');
|
logger.log('');
|
||||||
console.log(' 1) DES');
|
logger.info('Privacy Protocol:');
|
||||||
console.log(' 2) AES');
|
logger.dim(' 1) DES');
|
||||||
|
logger.dim(' 2) AES');
|
||||||
const defaultPrivProtocol = snmpConfig.privProtocol === 'AES' ? 2 : 1;
|
const defaultPrivProtocol = snmpConfig.privProtocol === 'AES' ? 2 : 1;
|
||||||
const privProtocolInput = await prompt(`Select Privacy Protocol [${defaultPrivProtocol}]: `);
|
const privProtocolInput = await prompt(`Select Privacy Protocol [${defaultPrivProtocol}]: `);
|
||||||
const privProtocol = parseInt(privProtocolInput, 10) || defaultPrivProtocol;
|
const privProtocol = parseInt(privProtocolInput, 10) || defaultPrivProtocol;
|
||||||
@@ -822,7 +831,8 @@ export class UpsHandler {
|
|||||||
thresholds: any,
|
thresholds: any,
|
||||||
prompt: (question: string) => Promise<string>,
|
prompt: (question: string) => Promise<string>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
console.log('\nShutdown Thresholds:');
|
logger.log('');
|
||||||
|
logger.info('Shutdown Thresholds:');
|
||||||
|
|
||||||
// Battery threshold
|
// Battery threshold
|
||||||
const defaultBatteryThreshold = thresholds.battery || 60;
|
const defaultBatteryThreshold = thresholds.battery || 60;
|
||||||
@@ -854,13 +864,14 @@ export class UpsHandler {
|
|||||||
snmpConfig: any,
|
snmpConfig: any,
|
||||||
prompt: (question: string) => Promise<string>,
|
prompt: (question: string) => Promise<string>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
console.log('\nUPS Model Selection:');
|
logger.log('');
|
||||||
console.log(' 1) CyberPower');
|
logger.info('UPS Model Selection:');
|
||||||
console.log(' 2) APC');
|
logger.dim(' 1) CyberPower');
|
||||||
console.log(' 3) Eaton');
|
logger.dim(' 2) APC');
|
||||||
console.log(' 4) TrippLite');
|
logger.dim(' 3) Eaton');
|
||||||
console.log(' 5) Liebert/Vertiv');
|
logger.dim(' 4) TrippLite');
|
||||||
console.log(' 6) Custom (Advanced)');
|
logger.dim(' 5) Liebert/Vertiv');
|
||||||
|
logger.dim(' 6) Custom (Advanced)');
|
||||||
|
|
||||||
const defaultModelValue = snmpConfig.upsModel === 'cyberpower'
|
const defaultModelValue = snmpConfig.upsModel === 'cyberpower'
|
||||||
? 1
|
? 1
|
||||||
@@ -891,8 +902,9 @@ export class UpsHandler {
|
|||||||
snmpConfig.upsModel = 'liebert';
|
snmpConfig.upsModel = 'liebert';
|
||||||
} else if (modelValue === 6) {
|
} else if (modelValue === 6) {
|
||||||
snmpConfig.upsModel = 'custom';
|
snmpConfig.upsModel = 'custom';
|
||||||
console.log('\nEnter custom OIDs for your UPS:');
|
logger.log('');
|
||||||
console.log('(Leave blank to use standard RFC 1628 OIDs as fallback)');
|
logger.info('Enter custom OIDs for your UPS:');
|
||||||
|
logger.dim('(Leave blank to use standard RFC 1628 OIDs as fallback)');
|
||||||
|
|
||||||
// Custom OIDs
|
// Custom OIDs
|
||||||
const powerStatusOID = await prompt('Power Status OID: ');
|
const powerStatusOID = await prompt('Power Status OID: ');
|
||||||
|
11
ts/daemon.ts
11
ts/daemon.ts
@@ -207,11 +207,9 @@ export class NupstDaemon {
|
|||||||
fs.writeFileSync(this.CONFIG_PATH, JSON.stringify(configToSave, null, 2));
|
fs.writeFileSync(this.CONFIG_PATH, JSON.stringify(configToSave, null, 2));
|
||||||
this.config = configToSave;
|
this.config = configToSave;
|
||||||
|
|
||||||
console.log('┌─ Configuration Saved ─────────────────────┐');
|
logger.logBox('Configuration Saved', [`Location: ${this.CONFIG_PATH}`], 45, 'success');
|
||||||
console.log(`│ Location: ${this.CONFIG_PATH}`);
|
|
||||||
console.log('└──────────────────────────────────────────┘');
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error saving configuration:', error);
|
logger.error(`Error saving configuration: ${error}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,10 +217,7 @@ export class NupstDaemon {
|
|||||||
* Helper method to log configuration errors consistently
|
* Helper method to log configuration errors consistently
|
||||||
*/
|
*/
|
||||||
private logConfigError(message: string): void {
|
private logConfigError(message: string): void {
|
||||||
console.error('┌─ Configuration Error ─────────────────────┐');
|
logger.logBox('Configuration Error', [message, "Please run 'nupst setup' first to create a configuration."], 45, 'error');
|
||||||
console.error(`│ ${message}`);
|
|
||||||
console.error("│ Please run 'nupst setup' first to create a configuration.");
|
|
||||||
console.error('└───────────────────────────────────────────┘');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -34,12 +34,14 @@ export class MigrationRunner {
|
|||||||
let currentConfig = config;
|
let currentConfig = config;
|
||||||
let anyMigrationsRan = false;
|
let anyMigrationsRan = false;
|
||||||
|
|
||||||
logger.dim('Checking for required config migrations...');
|
|
||||||
|
|
||||||
for (const migration of this.migrations) {
|
for (const migration of this.migrations) {
|
||||||
const shouldRun = await migration.shouldRun(currentConfig);
|
const shouldRun = await migration.shouldRun(currentConfig);
|
||||||
|
|
||||||
if (shouldRun) {
|
if (shouldRun) {
|
||||||
|
// Only show "checking" message when we actually need to migrate
|
||||||
|
if (!anyMigrationsRan) {
|
||||||
|
logger.dim('Checking for required config migrations...');
|
||||||
|
}
|
||||||
logger.info(`Running ${migration.getName()}...`);
|
logger.info(`Running ${migration.getName()}...`);
|
||||||
currentConfig = await migration.migrate(currentConfig);
|
currentConfig = await migration.migrate(currentConfig);
|
||||||
anyMigrationsRan = true;
|
anyMigrationsRan = true;
|
||||||
@@ -49,7 +51,7 @@ export class MigrationRunner {
|
|||||||
if (anyMigrationsRan) {
|
if (anyMigrationsRan) {
|
||||||
logger.success('Configuration migrations complete');
|
logger.success('Configuration migrations complete');
|
||||||
} else {
|
} else {
|
||||||
logger.dim('No migrations needed');
|
logger.success('config format ok');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@@ -50,11 +50,11 @@ WantedBy=multi-user.target
|
|||||||
try {
|
try {
|
||||||
await fs.access(configPath);
|
await fs.access(configPath);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('');
|
logger.log('');
|
||||||
console.log(`${symbols.error} ${theme.error('No configuration found')}`);
|
logger.error('No configuration found');
|
||||||
console.log(` ${theme.dim('Config file:')} ${configPath}`);
|
logger.log(` ${theme.dim('Config file:')} ${configPath}`);
|
||||||
console.log(` ${theme.dim('Run')} ${theme.command('nupst ups add')} ${theme.dim('to create a configuration')}`);
|
logger.log(` ${theme.dim('Run')} ${theme.command('nupst ups add')} ${theme.dim('to create a configuration')}`);
|
||||||
console.log('');
|
logger.log('');
|
||||||
throw new Error('Configuration not found');
|
throw new Error('Configuration not found');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,11 +192,11 @@ WantedBy=multi-user.target
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Display beautiful status
|
// Display beautiful status
|
||||||
console.log('');
|
logger.log('');
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
console.log(`${symbols.running} ${theme.success('Service:')} ${theme.statusActive('active (running)')}`);
|
logger.log(`${symbols.running} ${theme.success('Service:')} ${theme.statusActive('active (running)')}`);
|
||||||
} else {
|
} else {
|
||||||
console.log(`${symbols.stopped} ${theme.dim('Service:')} ${theme.statusInactive('inactive')}`);
|
logger.log(`${symbols.stopped} ${theme.dim('Service:')} ${theme.statusInactive('inactive')}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid || memory || cpu) {
|
if (pid || memory || cpu) {
|
||||||
@@ -204,14 +204,14 @@ WantedBy=multi-user.target
|
|||||||
if (pid) details.push(`PID: ${theme.dim(pid)}`);
|
if (pid) details.push(`PID: ${theme.dim(pid)}`);
|
||||||
if (memory) details.push(`Memory: ${theme.dim(memory)}`);
|
if (memory) details.push(`Memory: ${theme.dim(memory)}`);
|
||||||
if (cpu) details.push(`CPU: ${theme.dim(cpu)}`);
|
if (cpu) details.push(`CPU: ${theme.dim(cpu)}`);
|
||||||
console.log(` ${details.join(' ')}`);
|
logger.log(` ${details.join(' ')}`);
|
||||||
}
|
}
|
||||||
console.log('');
|
logger.log('');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('');
|
logger.log('');
|
||||||
console.log(`${symbols.stopped} ${theme.dim('Service:')} ${theme.statusInactive('not installed')}`);
|
logger.log(`${symbols.stopped} ${theme.dim('Service:')} ${theme.statusInactive('not installed')}`);
|
||||||
console.log('');
|
logger.log('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ WantedBy=multi-user.target
|
|||||||
|
|
||||||
// Check if we have the new multi-UPS config format
|
// Check if we have the new multi-UPS config format
|
||||||
if (config.upsDevices && Array.isArray(config.upsDevices) && config.upsDevices.length > 0) {
|
if (config.upsDevices && Array.isArray(config.upsDevices) && config.upsDevices.length > 0) {
|
||||||
console.log(theme.info(`UPS Devices (${config.upsDevices.length}):`));
|
logger.info(`UPS Devices (${config.upsDevices.length}):`);
|
||||||
|
|
||||||
// Show status for each UPS
|
// Show status for each UPS
|
||||||
for (const ups of config.upsDevices) {
|
for (const ups of config.upsDevices) {
|
||||||
@@ -236,7 +236,7 @@ WantedBy=multi-user.target
|
|||||||
}
|
}
|
||||||
} else if (config.snmp) {
|
} else if (config.snmp) {
|
||||||
// Legacy single UPS configuration
|
// Legacy single UPS configuration
|
||||||
console.log(theme.info('UPS Devices (1):'));
|
logger.info('UPS Devices (1):');
|
||||||
const legacyUps = {
|
const legacyUps = {
|
||||||
id: 'default',
|
id: 'default',
|
||||||
name: 'Default UPS',
|
name: 'Default UPS',
|
||||||
@@ -247,16 +247,16 @@ WantedBy=multi-user.target
|
|||||||
|
|
||||||
await this.displaySingleUpsStatus(legacyUps, snmp);
|
await this.displaySingleUpsStatus(legacyUps, snmp);
|
||||||
} else {
|
} else {
|
||||||
console.log('');
|
logger.log('');
|
||||||
console.log(`${symbols.warning} ${theme.warning('No UPS devices configured')}`);
|
logger.warn('No UPS devices configured');
|
||||||
console.log(` ${theme.dim('Run')} ${theme.command('nupst ups add')} ${theme.dim('to add a device')}`);
|
logger.log(` ${theme.dim('Run')} ${theme.command('nupst ups add')} ${theme.dim('to add a device')}`);
|
||||||
console.log('');
|
logger.log('');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('');
|
logger.log('');
|
||||||
console.log(`${symbols.error} ${theme.error('Failed to retrieve UPS status')}`);
|
logger.error('Failed to retrieve UPS status');
|
||||||
console.log(` ${theme.dim(error instanceof Error ? error.message : String(error))}`);
|
logger.log(` ${theme.dim(error instanceof Error ? error.message : String(error))}`);
|
||||||
console.log('');
|
logger.log('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,15 +284,15 @@ WantedBy=multi-user.target
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Display UPS name and power status
|
// Display UPS name and power status
|
||||||
console.log(` ${statusSymbol} ${theme.highlight(ups.name)} - ${formatPowerStatus(status.powerStatus)}`);
|
logger.log(` ${statusSymbol} ${theme.highlight(ups.name)} - ${formatPowerStatus(status.powerStatus)}`);
|
||||||
|
|
||||||
// Display battery with color coding
|
// Display battery with color coding
|
||||||
const batteryColor = getBatteryColor(status.batteryCapacity);
|
const batteryColor = getBatteryColor(status.batteryCapacity);
|
||||||
const batterySymbol = status.batteryCapacity >= ups.thresholds.battery ? symbols.success : symbols.warning;
|
const batterySymbol = status.batteryCapacity >= ups.thresholds.battery ? symbols.success : symbols.warning;
|
||||||
console.log(` Battery: ${batteryColor(status.batteryCapacity + '%')} ${batterySymbol} Runtime: ${getRuntimeColor(status.batteryRuntime)(status.batteryRuntime + ' min')}`);
|
logger.log(` Battery: ${batteryColor(status.batteryCapacity + '%')} ${batterySymbol} Runtime: ${getRuntimeColor(status.batteryRuntime)(status.batteryRuntime + ' min')}`);
|
||||||
|
|
||||||
// Display host info
|
// Display host info
|
||||||
console.log(` ${theme.dim(`Host: ${ups.snmp.host}:${ups.snmp.port}`)}`);
|
logger.log(` ${theme.dim(`Host: ${ups.snmp.host}:${ups.snmp.port}`)}`);
|
||||||
|
|
||||||
// Display groups if any
|
// Display groups if any
|
||||||
if (ups.groups && ups.groups.length > 0) {
|
if (ups.groups && ups.groups.length > 0) {
|
||||||
@@ -301,17 +301,17 @@ WantedBy=multi-user.target
|
|||||||
const group = config.groups?.find((g: { id: string }) => g.id === groupId);
|
const group = config.groups?.find((g: { id: string }) => g.id === groupId);
|
||||||
return group ? group.name : groupId;
|
return group ? group.name : groupId;
|
||||||
});
|
});
|
||||||
console.log(` ${theme.dim(`Groups: ${groupNames.join(', ')}`)}`);
|
logger.log(` ${theme.dim(`Groups: ${groupNames.join(', ')}`)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('');
|
logger.log('');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Display error for this UPS
|
// Display error for this UPS
|
||||||
console.log(` ${symbols.error} ${theme.highlight(ups.name)} - ${theme.error('Connection failed')}`);
|
logger.log(` ${symbols.error} ${theme.highlight(ups.name)} - ${theme.error('Connection failed')}`);
|
||||||
console.log(` ${theme.dim(error instanceof Error ? error.message : String(error))}`);
|
logger.log(` ${theme.dim(error instanceof Error ? error.message : String(error))}`);
|
||||||
console.log(` ${theme.dim(`Host: ${ups.snmp.host}:${ups.snmp.port}`)}`);
|
logger.log(` ${theme.dim(`Host: ${ups.snmp.host}:${ups.snmp.port}`)}`);
|
||||||
console.log('');
|
logger.log('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user