This commit is contained in:
2026-01-09 07:14:39 +00:00
parent 95da37590c
commit 05e1f94c79
22 changed files with 6549 additions and 10 deletions

View File

@@ -0,0 +1,377 @@
import { SnmpProtocol, SNMP_OIDS, type ISnmpOptions } from '../snmp/snmp.classes.snmpprotocol.js';
/**
* Extended UPS-MIB OIDs (RFC 1628)
*/
export const UPS_SNMP_OIDS = {
// Identity
upsIdentManufacturer: '1.3.6.1.2.1.33.1.1.1.0',
upsIdentModel: '1.3.6.1.2.1.33.1.1.2.0',
upsIdentUPSSoftwareVersion: '1.3.6.1.2.1.33.1.1.3.0',
upsIdentAgentSoftwareVersion: '1.3.6.1.2.1.33.1.1.4.0',
upsIdentName: '1.3.6.1.2.1.33.1.1.5.0',
upsIdentAttachedDevices: '1.3.6.1.2.1.33.1.1.6.0',
// Battery group
upsBatteryStatus: '1.3.6.1.2.1.33.1.2.1.0',
upsSecondsOnBattery: '1.3.6.1.2.1.33.1.2.2.0',
upsEstimatedMinutesRemaining: '1.3.6.1.2.1.33.1.2.3.0',
upsEstimatedChargeRemaining: '1.3.6.1.2.1.33.1.2.4.0',
upsBatteryVoltage: '1.3.6.1.2.1.33.1.2.5.0',
upsBatteryCurrent: '1.3.6.1.2.1.33.1.2.6.0',
upsBatteryTemperature: '1.3.6.1.2.1.33.1.2.7.0',
// Input group
upsInputLineBads: '1.3.6.1.2.1.33.1.3.1.0',
upsInputNumLines: '1.3.6.1.2.1.33.1.3.2.0',
upsInputLineIndex: '1.3.6.1.2.1.33.1.3.3.1.1',
upsInputFrequency: '1.3.6.1.2.1.33.1.3.3.1.2',
upsInputVoltage: '1.3.6.1.2.1.33.1.3.3.1.3',
upsInputCurrent: '1.3.6.1.2.1.33.1.3.3.1.4',
upsInputTruePower: '1.3.6.1.2.1.33.1.3.3.1.5',
// Output group
upsOutputSource: '1.3.6.1.2.1.33.1.4.1.0',
upsOutputFrequency: '1.3.6.1.2.1.33.1.4.2.0',
upsOutputNumLines: '1.3.6.1.2.1.33.1.4.3.0',
upsOutputLineIndex: '1.3.6.1.2.1.33.1.4.4.1.1',
upsOutputVoltage: '1.3.6.1.2.1.33.1.4.4.1.2',
upsOutputCurrent: '1.3.6.1.2.1.33.1.4.4.1.3',
upsOutputPower: '1.3.6.1.2.1.33.1.4.4.1.4',
upsOutputPercentLoad: '1.3.6.1.2.1.33.1.4.4.1.5',
// Bypass group
upsBypassFrequency: '1.3.6.1.2.1.33.1.5.1.0',
upsBypassNumLines: '1.3.6.1.2.1.33.1.5.2.0',
// Alarm group
upsAlarmsPresent: '1.3.6.1.2.1.33.1.6.1.0',
// Test group
upsTestId: '1.3.6.1.2.1.33.1.7.1.0',
upsTestSpinLock: '1.3.6.1.2.1.33.1.7.2.0',
upsTestResultsSummary: '1.3.6.1.2.1.33.1.7.3.0',
upsTestResultsDetail: '1.3.6.1.2.1.33.1.7.4.0',
upsTestStartTime: '1.3.6.1.2.1.33.1.7.5.0',
upsTestElapsedTime: '1.3.6.1.2.1.33.1.7.6.0',
// Control group
upsShutdownType: '1.3.6.1.2.1.33.1.8.1.0',
upsShutdownAfterDelay: '1.3.6.1.2.1.33.1.8.2.0',
upsStartupAfterDelay: '1.3.6.1.2.1.33.1.8.3.0',
upsRebootWithDuration: '1.3.6.1.2.1.33.1.8.4.0',
upsAutoRestart: '1.3.6.1.2.1.33.1.8.5.0',
// Config group
upsConfigInputVoltage: '1.3.6.1.2.1.33.1.9.1.0',
upsConfigInputFreq: '1.3.6.1.2.1.33.1.9.2.0',
upsConfigOutputVoltage: '1.3.6.1.2.1.33.1.9.3.0',
upsConfigOutputFreq: '1.3.6.1.2.1.33.1.9.4.0',
upsConfigOutputVA: '1.3.6.1.2.1.33.1.9.5.0',
upsConfigOutputPower: '1.3.6.1.2.1.33.1.9.6.0',
upsConfigLowBattTime: '1.3.6.1.2.1.33.1.9.7.0',
upsConfigAudibleStatus: '1.3.6.1.2.1.33.1.9.8.0',
upsConfigLowVoltageTransferPoint: '1.3.6.1.2.1.33.1.9.9.0',
upsConfigHighVoltageTransferPoint: '1.3.6.1.2.1.33.1.9.10.0',
};
/**
* Battery status values from UPS-MIB
*/
export type TUpsBatteryStatus =
| 'unknown'
| 'batteryNormal'
| 'batteryLow'
| 'batteryDepleted';
/**
* Output source values from UPS-MIB
*/
export type TUpsOutputSource =
| 'other'
| 'none'
| 'normal'
| 'bypass'
| 'battery'
| 'booster'
| 'reducer';
/**
* Test results summary from UPS-MIB
*/
export type TUpsTestResult =
| 'donePass'
| 'doneWarning'
| 'doneError'
| 'aborted'
| 'inProgress'
| 'noTestsInitiated';
/**
* SNMP-based UPS status interface
*/
export interface IUpsSnmpStatus {
batteryStatus: TUpsBatteryStatus;
secondsOnBattery: number;
estimatedMinutesRemaining: number;
estimatedChargeRemaining: number;
batteryVoltage: number;
batteryTemperature: number;
outputSource: TUpsOutputSource;
outputFrequency: number;
outputVoltage: number;
outputCurrent: number;
outputPower: number;
outputPercentLoad: number;
inputFrequency: number;
inputVoltage: number;
alarmsPresent: number;
}
/**
* UPS SNMP handler for querying UPS devices via SNMP
*/
export class UpsSnmpHandler {
private protocol: SnmpProtocol;
constructor(address: string, options?: ISnmpOptions) {
this.protocol = new SnmpProtocol(address, options);
}
/**
* Close SNMP session
*/
public close(): void {
this.protocol.close();
}
/**
* Get UPS identity information
*/
public async getIdentity(): Promise<{
manufacturer: string;
model: string;
softwareVersion: string;
name: string;
}> {
const varbinds = await this.protocol.getMultiple([
UPS_SNMP_OIDS.upsIdentManufacturer,
UPS_SNMP_OIDS.upsIdentModel,
UPS_SNMP_OIDS.upsIdentUPSSoftwareVersion,
UPS_SNMP_OIDS.upsIdentName,
]);
const getValue = (oid: string): string => {
const vb = varbinds.find((v) => v.oid === oid);
return String(vb?.value || '');
};
return {
manufacturer: getValue(UPS_SNMP_OIDS.upsIdentManufacturer),
model: getValue(UPS_SNMP_OIDS.upsIdentModel),
softwareVersion: getValue(UPS_SNMP_OIDS.upsIdentUPSSoftwareVersion),
name: getValue(UPS_SNMP_OIDS.upsIdentName),
};
}
/**
* Get battery status
*/
public async getBatteryStatus(): Promise<{
status: TUpsBatteryStatus;
secondsOnBattery: number;
estimatedMinutesRemaining: number;
estimatedChargeRemaining: number;
voltage: number;
temperature: number;
}> {
const varbinds = await this.protocol.getMultiple([
UPS_SNMP_OIDS.upsBatteryStatus,
UPS_SNMP_OIDS.upsSecondsOnBattery,
UPS_SNMP_OIDS.upsEstimatedMinutesRemaining,
UPS_SNMP_OIDS.upsEstimatedChargeRemaining,
UPS_SNMP_OIDS.upsBatteryVoltage,
UPS_SNMP_OIDS.upsBatteryTemperature,
]);
const getValue = (oid: string): number => {
const vb = varbinds.find((v) => v.oid === oid);
return Number(vb?.value || 0);
};
const statusMap: Record<number, TUpsBatteryStatus> = {
1: 'unknown',
2: 'batteryNormal',
3: 'batteryLow',
4: 'batteryDepleted',
};
return {
status: statusMap[getValue(UPS_SNMP_OIDS.upsBatteryStatus)] || 'unknown',
secondsOnBattery: getValue(UPS_SNMP_OIDS.upsSecondsOnBattery),
estimatedMinutesRemaining: getValue(UPS_SNMP_OIDS.upsEstimatedMinutesRemaining),
estimatedChargeRemaining: getValue(UPS_SNMP_OIDS.upsEstimatedChargeRemaining),
voltage: getValue(UPS_SNMP_OIDS.upsBatteryVoltage) / 10, // Typically in 0.1V units
temperature: getValue(UPS_SNMP_OIDS.upsBatteryTemperature),
};
}
/**
* Get input status
*/
public async getInputStatus(): Promise<{
frequency: number;
voltage: number;
lineBads: number;
}> {
const varbinds = await this.protocol.getMultiple([
UPS_SNMP_OIDS.upsInputFrequency + '.1', // Line 1
UPS_SNMP_OIDS.upsInputVoltage + '.1', // Line 1
UPS_SNMP_OIDS.upsInputLineBads,
]);
const getValue = (oid: string): number => {
const vb = varbinds.find((v) => v.oid === oid);
return Number(vb?.value || 0);
};
return {
frequency: getValue(UPS_SNMP_OIDS.upsInputFrequency + '.1') / 10, // 0.1 Hz units
voltage: getValue(UPS_SNMP_OIDS.upsInputVoltage + '.1'),
lineBads: getValue(UPS_SNMP_OIDS.upsInputLineBads),
};
}
/**
* Get output status
*/
public async getOutputStatus(): Promise<{
source: TUpsOutputSource;
frequency: number;
voltage: number;
current: number;
power: number;
percentLoad: number;
}> {
const varbinds = await this.protocol.getMultiple([
UPS_SNMP_OIDS.upsOutputSource,
UPS_SNMP_OIDS.upsOutputFrequency,
UPS_SNMP_OIDS.upsOutputVoltage + '.1', // Line 1
UPS_SNMP_OIDS.upsOutputCurrent + '.1', // Line 1
UPS_SNMP_OIDS.upsOutputPower + '.1', // Line 1
UPS_SNMP_OIDS.upsOutputPercentLoad + '.1', // Line 1
]);
const getValue = (oid: string): number => {
const vb = varbinds.find((v) => v.oid === oid);
return Number(vb?.value || 0);
};
const sourceMap: Record<number, TUpsOutputSource> = {
1: 'other',
2: 'none',
3: 'normal',
4: 'bypass',
5: 'battery',
6: 'booster',
7: 'reducer',
};
return {
source: sourceMap[getValue(UPS_SNMP_OIDS.upsOutputSource)] || 'other',
frequency: getValue(UPS_SNMP_OIDS.upsOutputFrequency) / 10, // 0.1 Hz units
voltage: getValue(UPS_SNMP_OIDS.upsOutputVoltage + '.1'),
current: getValue(UPS_SNMP_OIDS.upsOutputCurrent + '.1') / 10, // 0.1 A units
power: getValue(UPS_SNMP_OIDS.upsOutputPower + '.1'),
percentLoad: getValue(UPS_SNMP_OIDS.upsOutputPercentLoad + '.1'),
};
}
/**
* Get full UPS status
*/
public async getFullStatus(): Promise<IUpsSnmpStatus> {
const [battery, input, output] = await Promise.all([
this.getBatteryStatus(),
this.getInputStatus(),
this.getOutputStatus(),
]);
// Get alarms separately
let alarmsPresent = 0;
try {
const alarmVb = await this.protocol.get(UPS_SNMP_OIDS.upsAlarmsPresent);
alarmsPresent = Number(alarmVb.value || 0);
} catch {
// Ignore alarm fetch errors
}
return {
batteryStatus: battery.status,
secondsOnBattery: battery.secondsOnBattery,
estimatedMinutesRemaining: battery.estimatedMinutesRemaining,
estimatedChargeRemaining: battery.estimatedChargeRemaining,
batteryVoltage: battery.voltage,
batteryTemperature: battery.temperature,
outputSource: output.source,
outputFrequency: output.frequency,
outputVoltage: output.voltage,
outputCurrent: output.current,
outputPower: output.power,
outputPercentLoad: output.percentLoad,
inputFrequency: input.frequency,
inputVoltage: input.voltage,
alarmsPresent,
};
}
/**
* Check if UPS-MIB is supported on device
*/
public async isUpsDevice(): Promise<boolean> {
try {
const vb = await this.protocol.get(UPS_SNMP_OIDS.upsBatteryStatus);
return vb.value !== null && vb.value !== undefined;
} catch {
return false;
}
}
/**
* Get configuration info
*/
public async getConfiguration(): Promise<{
inputVoltage: number;
inputFrequency: number;
outputVoltage: number;
outputFrequency: number;
outputVA: number;
outputPower: number;
lowBatteryTime: number;
}> {
const varbinds = await this.protocol.getMultiple([
UPS_SNMP_OIDS.upsConfigInputVoltage,
UPS_SNMP_OIDS.upsConfigInputFreq,
UPS_SNMP_OIDS.upsConfigOutputVoltage,
UPS_SNMP_OIDS.upsConfigOutputFreq,
UPS_SNMP_OIDS.upsConfigOutputVA,
UPS_SNMP_OIDS.upsConfigOutputPower,
UPS_SNMP_OIDS.upsConfigLowBattTime,
]);
const getValue = (oid: string): number => {
const vb = varbinds.find((v) => v.oid === oid);
return Number(vb?.value || 0);
};
return {
inputVoltage: getValue(UPS_SNMP_OIDS.upsConfigInputVoltage),
inputFrequency: getValue(UPS_SNMP_OIDS.upsConfigInputFreq) / 10,
outputVoltage: getValue(UPS_SNMP_OIDS.upsConfigOutputVoltage),
outputFrequency: getValue(UPS_SNMP_OIDS.upsConfigOutputFreq) / 10,
outputVA: getValue(UPS_SNMP_OIDS.upsConfigOutputVA),
outputPower: getValue(UPS_SNMP_OIDS.upsConfigOutputPower),
lowBatteryTime: getValue(UPS_SNMP_OIDS.upsConfigLowBattTime),
};
}
}