Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
bb87316dd3 | |||
d6e0a1a274 | |||
95fa4f8b0b | |||
c2f2f1e2ee |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@serve.zone/nupst",
|
"name": "@serve.zone/nupst",
|
||||||
"version": "4.0.7",
|
"version": "4.1.1",
|
||||||
"exports": "./mod.ts",
|
"exports": "./mod.ts",
|
||||||
"tasks": {
|
"tasks": {
|
||||||
"dev": "deno run --allow-all mod.ts",
|
"dev": "deno run --allow-all mod.ts",
|
||||||
|
@@ -133,22 +133,47 @@ export class ServiceHandler {
|
|||||||
);
|
);
|
||||||
|
|
||||||
console.log('');
|
console.log('');
|
||||||
logger.info('Updating NUPST to latest version...');
|
logger.info('Checking for updates...');
|
||||||
console.log('');
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Get current version
|
||||||
|
const currentVersion = this.nupst.getVersion();
|
||||||
|
|
||||||
|
// Fetch latest version from Gitea API
|
||||||
|
const apiUrl = 'https://code.foss.global/api/v1/repos/serve.zone/nupst/releases/latest';
|
||||||
|
const response = execSync(`curl -sSL ${apiUrl}`).toString();
|
||||||
|
const release = JSON.parse(response);
|
||||||
|
const latestVersion = release.tag_name; // e.g., "v4.0.7"
|
||||||
|
|
||||||
|
// Normalize versions for comparison (ensure both have "v" prefix)
|
||||||
|
const normalizedCurrent = currentVersion.startsWith('v') ? currentVersion : `v${currentVersion}`;
|
||||||
|
const normalizedLatest = latestVersion.startsWith('v') ? latestVersion : `v${latestVersion}`;
|
||||||
|
|
||||||
|
logger.dim(`Current version: ${normalizedCurrent}`);
|
||||||
|
logger.dim(`Latest version: ${normalizedLatest}`);
|
||||||
|
console.log('');
|
||||||
|
|
||||||
|
// Compare normalized versions
|
||||||
|
if (normalizedCurrent === normalizedLatest) {
|
||||||
|
logger.success('Already up to date!');
|
||||||
|
console.log('');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(`New version available: ${latestVersion}`);
|
||||||
|
logger.dim('Downloading and installing...');
|
||||||
|
console.log('');
|
||||||
|
|
||||||
// Download and run the install script
|
// Download and run the install script
|
||||||
// This handles everything: download binary, stop service, replace, restart
|
// This handles everything: download binary, stop service, replace, restart
|
||||||
const installUrl = 'https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh';
|
const installUrl = 'https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh';
|
||||||
|
|
||||||
logger.dim('Downloading install script...');
|
|
||||||
execSync(`curl -sSL ${installUrl} | bash`, {
|
execSync(`curl -sSL ${installUrl} | bash`, {
|
||||||
stdio: 'inherit', // Show install script output to user
|
stdio: 'inherit', // Show install script output to user
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('');
|
console.log('');
|
||||||
logger.success('Update completed successfully!');
|
logger.success(`Updated to ${latestVersion}`);
|
||||||
logger.dim('Run "nupst service status" to verify the update.');
|
|
||||||
console.log('');
|
console.log('');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('');
|
console.log('');
|
||||||
|
@@ -525,6 +525,7 @@ export class NupstSnmp {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine power status based on UPS model and raw value
|
* Determine power status based on UPS model and raw value
|
||||||
|
* Uses the value mappings defined in the OID sets
|
||||||
* @param upsModel UPS model
|
* @param upsModel UPS model
|
||||||
* @param powerStatusValue Raw power status value
|
* @param powerStatusValue Raw power status value
|
||||||
* @returns Standardized power status
|
* @returns Standardized power status
|
||||||
@@ -533,38 +534,27 @@ export class NupstSnmp {
|
|||||||
upsModel: TUpsModel | undefined,
|
upsModel: TUpsModel | undefined,
|
||||||
powerStatusValue: number,
|
powerStatusValue: number,
|
||||||
): 'online' | 'onBattery' | 'unknown' {
|
): 'online' | 'onBattery' | 'unknown' {
|
||||||
if (upsModel === 'cyberpower') {
|
// Get the OID set for this UPS model
|
||||||
// CyberPower RMCARD205: upsBaseOutputStatus values
|
if (upsModel && upsModel !== 'custom') {
|
||||||
// 2=onLine, 3=onBattery, 4=onBoost, 5=onSleep, 6=off, etc.
|
const oidSet = UpsOidSets.getOidSet(upsModel);
|
||||||
if (powerStatusValue === 2) {
|
|
||||||
|
// Use the value mappings if available
|
||||||
|
if (oidSet.POWER_STATUS_VALUES) {
|
||||||
|
if (powerStatusValue === oidSet.POWER_STATUS_VALUES.online) {
|
||||||
return 'online';
|
return 'online';
|
||||||
} else if (powerStatusValue === 3) {
|
} else if (powerStatusValue === oidSet.POWER_STATUS_VALUES.onBattery) {
|
||||||
return 'onBattery';
|
return 'onBattery';
|
||||||
}
|
}
|
||||||
} else if (upsModel === 'eaton') {
|
}
|
||||||
// Eaton UPS: xupsOutputSource values
|
}
|
||||||
// 3=normal/mains, 5=battery, etc.
|
|
||||||
|
// Fallback for custom or undefined models (RFC 1628 standard)
|
||||||
|
// upsOutputSource: 3=normal (mains), 5=battery
|
||||||
if (powerStatusValue === 3) {
|
if (powerStatusValue === 3) {
|
||||||
return 'online';
|
return 'online';
|
||||||
} else if (powerStatusValue === 5) {
|
} else if (powerStatusValue === 5) {
|
||||||
return 'onBattery';
|
return 'onBattery';
|
||||||
}
|
}
|
||||||
} else if (upsModel === 'apc') {
|
|
||||||
// APC UPS: upsBasicOutputStatus values
|
|
||||||
// 2=online, 3=onBattery, etc.
|
|
||||||
if (powerStatusValue === 2) {
|
|
||||||
return 'online';
|
|
||||||
} else if (powerStatusValue === 3) {
|
|
||||||
return 'onBattery';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Default interpretation for other UPS models
|
|
||||||
if (powerStatusValue === 1) {
|
|
||||||
return 'online';
|
|
||||||
} else if (powerStatusValue === 2) {
|
|
||||||
return 'onBattery';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'unknown';
|
return 'unknown';
|
||||||
}
|
}
|
||||||
|
@@ -11,37 +11,57 @@ export class UpsOidSets {
|
|||||||
private static readonly UPS_OID_SETS: Record<TUpsModel, IOidSet> = {
|
private static readonly UPS_OID_SETS: Record<TUpsModel, IOidSet> = {
|
||||||
// Cyberpower OIDs for RMCARD205 (based on CyberPower_MIB_v2.11)
|
// Cyberpower OIDs for RMCARD205 (based on CyberPower_MIB_v2.11)
|
||||||
cyberpower: {
|
cyberpower: {
|
||||||
POWER_STATUS: '1.3.6.1.4.1.3808.1.1.1.4.1.1.0', // upsBaseOutputStatus (2=online, 3=on battery)
|
POWER_STATUS: '1.3.6.1.4.1.3808.1.1.1.4.1.1.0', // upsBaseOutputStatus
|
||||||
BATTERY_CAPACITY: '1.3.6.1.4.1.3808.1.1.1.2.2.1.0', // upsAdvanceBatteryCapacity (percentage)
|
BATTERY_CAPACITY: '1.3.6.1.4.1.3808.1.1.1.2.2.1.0', // upsAdvanceBatteryCapacity (percentage)
|
||||||
BATTERY_RUNTIME: '1.3.6.1.4.1.3808.1.1.1.2.2.4.0', // upsAdvanceBatteryRunTimeRemaining (TimeTicks)
|
BATTERY_RUNTIME: '1.3.6.1.4.1.3808.1.1.1.2.2.4.0', // upsAdvanceBatteryRunTimeRemaining (TimeTicks)
|
||||||
|
POWER_STATUS_VALUES: {
|
||||||
|
online: 2, // upsBaseOutputStatus: 2=onLine
|
||||||
|
onBattery: 3, // upsBaseOutputStatus: 3=onBattery
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// APC OIDs
|
// APC OIDs
|
||||||
apc: {
|
apc: {
|
||||||
POWER_STATUS: '1.3.6.1.4.1.318.1.1.1.4.1.1.0', // Power status (1=online, 2=on battery)
|
POWER_STATUS: '1.3.6.1.4.1.318.1.1.1.4.1.1.0', // upsBasicOutputStatus
|
||||||
BATTERY_CAPACITY: '1.3.6.1.4.1.318.1.1.1.2.2.1.0', // Battery capacity in percentage
|
BATTERY_CAPACITY: '1.3.6.1.4.1.318.1.1.1.2.2.1.0', // Battery capacity in percentage
|
||||||
BATTERY_RUNTIME: '1.3.6.1.4.1.318.1.1.1.2.2.3.0', // Remaining runtime in minutes
|
BATTERY_RUNTIME: '1.3.6.1.4.1.318.1.1.1.2.2.3.0', // Remaining runtime in minutes
|
||||||
|
POWER_STATUS_VALUES: {
|
||||||
|
online: 2, // upsBasicOutputStatus: 2=onLine
|
||||||
|
onBattery: 3, // upsBasicOutputStatus: 3=onBattery
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// Eaton OIDs
|
// Eaton OIDs
|
||||||
eaton: {
|
eaton: {
|
||||||
POWER_STATUS: '1.3.6.1.4.1.534.1.4.4.0', // xupsOutputSource (3=normal/mains, 5=battery)
|
POWER_STATUS: '1.3.6.1.4.1.534.1.4.4.0', // xupsOutputSource
|
||||||
BATTERY_CAPACITY: '1.3.6.1.4.1.534.1.2.4.0', // xupsBatCapacity (percentage)
|
BATTERY_CAPACITY: '1.3.6.1.4.1.534.1.2.4.0', // xupsBatCapacity (percentage)
|
||||||
BATTERY_RUNTIME: '1.3.6.1.4.1.534.1.2.1.0', // xupsBatTimeRemaining (seconds)
|
BATTERY_RUNTIME: '1.3.6.1.4.1.534.1.2.1.0', // xupsBatTimeRemaining (seconds)
|
||||||
|
POWER_STATUS_VALUES: {
|
||||||
|
online: 3, // xupsOutputSource: 3=normal (mains power)
|
||||||
|
onBattery: 5, // xupsOutputSource: 5=battery
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// TrippLite OIDs
|
// TrippLite OIDs
|
||||||
tripplite: {
|
tripplite: {
|
||||||
POWER_STATUS: '1.3.6.1.4.1.850.1.1.3.1.1.1.0', // Power status
|
POWER_STATUS: '1.3.6.1.4.1.850.1.1.3.1.1.1.0', // tlUpsOutputSource
|
||||||
BATTERY_CAPACITY: '1.3.6.1.4.1.850.1.1.3.2.4.1.0', // Battery capacity in percentage
|
BATTERY_CAPACITY: '1.3.6.1.4.1.850.1.1.3.2.4.1.0', // Battery capacity in percentage
|
||||||
BATTERY_RUNTIME: '1.3.6.1.4.1.850.1.1.3.2.2.1.0', // Remaining runtime in minutes
|
BATTERY_RUNTIME: '1.3.6.1.4.1.850.1.1.3.2.2.1.0', // Remaining runtime in minutes
|
||||||
|
POWER_STATUS_VALUES: {
|
||||||
|
online: 2, // tlUpsOutputSource: 2=normal (mains power)
|
||||||
|
onBattery: 3, // tlUpsOutputSource: 3=onBattery
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// Liebert/Vertiv OIDs
|
// Liebert/Vertiv OIDs
|
||||||
liebert: {
|
liebert: {
|
||||||
POWER_STATUS: '1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.1.2.1', // Power status
|
POWER_STATUS: '1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.1.2.1', // lgpPwrOutputSource
|
||||||
BATTERY_CAPACITY: '1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.1.4.1', // Battery capacity in percentage
|
BATTERY_CAPACITY: '1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.1.4.1', // Battery capacity in percentage
|
||||||
BATTERY_RUNTIME: '1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.1.5.1', // Remaining runtime in minutes
|
BATTERY_RUNTIME: '1.3.6.1.4.1.476.1.42.3.9.20.1.20.1.2.1.5.1', // Remaining runtime in minutes
|
||||||
|
POWER_STATUS_VALUES: {
|
||||||
|
online: 2, // lgpPwrOutputSource: 2=normal (mains power)
|
||||||
|
onBattery: 3, // lgpPwrOutputSource: 3=onBattery
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// Custom OIDs (to be provided by the user)
|
// Custom OIDs (to be provided by the user)
|
||||||
|
@@ -28,6 +28,13 @@ export interface IOidSet {
|
|||||||
BATTERY_CAPACITY: string;
|
BATTERY_CAPACITY: string;
|
||||||
/** OID for battery runtime */
|
/** OID for battery runtime */
|
||||||
BATTERY_RUNTIME: string;
|
BATTERY_RUNTIME: string;
|
||||||
|
/** Power status value mappings */
|
||||||
|
POWER_STATUS_VALUES?: {
|
||||||
|
/** SNMP value that indicates UPS is online (on AC power) */
|
||||||
|
online: number;
|
||||||
|
/** SNMP value that indicates UPS is on battery */
|
||||||
|
onBattery: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -50,11 +50,11 @@ WantedBy=multi-user.target
|
|||||||
try {
|
try {
|
||||||
await fs.access(configPath);
|
await fs.access(configPath);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const boxWidth = 50;
|
console.log('');
|
||||||
logger.logBoxTitle('Configuration Error', boxWidth);
|
console.log(`${symbols.error} ${theme.error('No configuration found')}`);
|
||||||
logger.logBoxLine(`No configuration file found at ${configPath}`);
|
console.log(` ${theme.dim('Config file:')} ${configPath}`);
|
||||||
logger.logBoxLine("Please run 'nupst add' first to create a UPS configuration.");
|
console.log(` ${theme.dim('Run')} ${theme.command('nupst ups add')} ${theme.dim('to create a configuration')}`);
|
||||||
logger.logBoxEnd();
|
console.log('');
|
||||||
throw new Error('Configuration not found');
|
throw new Error('Configuration not found');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,16 +138,12 @@ WantedBy=multi-user.target
|
|||||||
try {
|
try {
|
||||||
// Enable debug mode if requested
|
// Enable debug mode if requested
|
||||||
if (debugMode) {
|
if (debugMode) {
|
||||||
const boxWidth = 45;
|
console.log('');
|
||||||
logger.logBoxTitle('Debug Mode', boxWidth);
|
logger.info('Debug Mode: SNMP debugging enabled');
|
||||||
logger.logBoxLine('SNMP debugging enabled - detailed logs will be shown');
|
console.log('');
|
||||||
logger.logBoxEnd();
|
|
||||||
this.daemon.getNupstSnmp().enableDebug();
|
this.daemon.getNupstSnmp().enableDebug();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display version information
|
|
||||||
this.daemon.getNupstSnmp().getNupst().logVersionInfo();
|
|
||||||
|
|
||||||
// Check if config exists first
|
// Check if config exists first
|
||||||
try {
|
try {
|
||||||
await this.checkConfigExists();
|
await this.checkConfigExists();
|
||||||
|
Reference in New Issue
Block a user