272 lines
6.3 KiB
TypeScript
272 lines
6.3 KiB
TypeScript
import * as plugins from '../plugins.js';
|
|
import { Device } from '../abstract/device.abstract.js';
|
|
import { SnmpProtocol, SNMP_OIDS, type ISnmpOptions, type ISnmpVarbind } from './snmp.classes.snmpprotocol.js';
|
|
import type { IDeviceInfo, IRetryOptions, TDeviceStatus } from '../interfaces/index.js';
|
|
|
|
/**
|
|
* SNMP device information
|
|
*/
|
|
export interface ISnmpDeviceInfo extends IDeviceInfo {
|
|
type: 'snmp';
|
|
sysDescr: string;
|
|
sysObjectID: string;
|
|
sysUpTime: number;
|
|
sysContact?: string;
|
|
sysName?: string;
|
|
sysLocation?: string;
|
|
}
|
|
|
|
/**
|
|
* SNMP Device class for generic SNMP-enabled devices
|
|
*/
|
|
export class SnmpDevice extends Device {
|
|
private protocol: SnmpProtocol | null = null;
|
|
private snmpOptions: ISnmpOptions;
|
|
|
|
private _sysDescr: string = '';
|
|
private _sysObjectID: string = '';
|
|
private _sysUpTime: number = 0;
|
|
private _sysContact?: string;
|
|
private _sysName?: string;
|
|
private _sysLocation?: string;
|
|
|
|
constructor(
|
|
info: IDeviceInfo,
|
|
snmpOptions?: ISnmpOptions,
|
|
retryOptions?: IRetryOptions
|
|
) {
|
|
super(info, retryOptions);
|
|
this.snmpOptions = { port: info.port, ...snmpOptions };
|
|
}
|
|
|
|
// Getters for SNMP properties
|
|
public get sysDescr(): string {
|
|
return this._sysDescr;
|
|
}
|
|
|
|
public get sysObjectID(): string {
|
|
return this._sysObjectID;
|
|
}
|
|
|
|
public get sysUpTime(): number {
|
|
return this._sysUpTime;
|
|
}
|
|
|
|
public get sysContact(): string | undefined {
|
|
return this._sysContact;
|
|
}
|
|
|
|
public get sysName(): string | undefined {
|
|
return this._sysName;
|
|
}
|
|
|
|
public get sysLocation(): string | undefined {
|
|
return this._sysLocation;
|
|
}
|
|
|
|
/**
|
|
* Connect to the SNMP device
|
|
*/
|
|
protected async doConnect(): Promise<void> {
|
|
this.protocol = new SnmpProtocol(this.address, this.snmpOptions);
|
|
|
|
// Verify connection by fetching system info
|
|
const sysInfo = await this.protocol.getSystemInfo();
|
|
|
|
this._sysDescr = sysInfo.sysDescr;
|
|
this._sysObjectID = sysInfo.sysObjectID;
|
|
this._sysUpTime = sysInfo.sysUpTime;
|
|
this._sysContact = sysInfo.sysContact || undefined;
|
|
this._sysName = sysInfo.sysName || undefined;
|
|
this._sysLocation = sysInfo.sysLocation || undefined;
|
|
|
|
// Update device name if sysName is available
|
|
if (sysInfo.sysName && !this.name.includes('SNMP Device')) {
|
|
// Keep custom name
|
|
} else if (sysInfo.sysName) {
|
|
(this as { name: string }).name = sysInfo.sysName;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disconnect from the SNMP device
|
|
*/
|
|
protected async doDisconnect(): Promise<void> {
|
|
if (this.protocol) {
|
|
this.protocol.close();
|
|
this.protocol = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Refresh device status
|
|
*/
|
|
public async refreshStatus(): Promise<void> {
|
|
if (!this.protocol) {
|
|
throw new Error('Not connected');
|
|
}
|
|
|
|
const sysInfo = await this.protocol.getSystemInfo();
|
|
this._sysUpTime = sysInfo.sysUpTime;
|
|
this.emit('status:updated', this.getDeviceInfo());
|
|
}
|
|
|
|
/**
|
|
* Get a single OID value
|
|
*/
|
|
public async get(oid: string): Promise<ISnmpVarbind> {
|
|
if (!this.protocol) {
|
|
throw new Error('Not connected');
|
|
}
|
|
return this.protocol.get(oid);
|
|
}
|
|
|
|
/**
|
|
* Get multiple OID values
|
|
*/
|
|
public async getMultiple(oids: string[]): Promise<ISnmpVarbind[]> {
|
|
if (!this.protocol) {
|
|
throw new Error('Not connected');
|
|
}
|
|
return this.protocol.getMultiple(oids);
|
|
}
|
|
|
|
/**
|
|
* Get next OID in the MIB tree
|
|
*/
|
|
public async getNext(oid: string): Promise<ISnmpVarbind> {
|
|
if (!this.protocol) {
|
|
throw new Error('Not connected');
|
|
}
|
|
return this.protocol.getNext(oid);
|
|
}
|
|
|
|
/**
|
|
* GETBULK operation for efficient table retrieval
|
|
*/
|
|
public async getBulk(
|
|
oids: string[],
|
|
nonRepeaters?: number,
|
|
maxRepetitions?: number
|
|
): Promise<ISnmpVarbind[]> {
|
|
if (!this.protocol) {
|
|
throw new Error('Not connected');
|
|
}
|
|
return this.protocol.getBulk(oids, nonRepeaters, maxRepetitions);
|
|
}
|
|
|
|
/**
|
|
* Walk a MIB tree
|
|
*/
|
|
public async walk(baseOid: string): Promise<ISnmpVarbind[]> {
|
|
if (!this.protocol) {
|
|
throw new Error('Not connected');
|
|
}
|
|
return this.protocol.walk(baseOid);
|
|
}
|
|
|
|
/**
|
|
* Set an OID value
|
|
*/
|
|
public async set(
|
|
oid: string,
|
|
type: 'Integer' | 'OctetString' | 'ObjectIdentifier' | 'IpAddress',
|
|
value: unknown
|
|
): Promise<ISnmpVarbind> {
|
|
if (!this.protocol) {
|
|
throw new Error('Not connected');
|
|
}
|
|
return this.protocol.set(oid, type, value);
|
|
}
|
|
|
|
/**
|
|
* Get device information
|
|
*/
|
|
public getDeviceInfo(): ISnmpDeviceInfo {
|
|
return {
|
|
id: this.id,
|
|
name: this.name,
|
|
type: 'snmp',
|
|
address: this.address,
|
|
port: this.port,
|
|
status: this.status,
|
|
sysDescr: this._sysDescr,
|
|
sysObjectID: this._sysObjectID,
|
|
sysUpTime: this._sysUpTime,
|
|
sysContact: this._sysContact,
|
|
sysName: this._sysName,
|
|
sysLocation: this._sysLocation,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create SnmpDevice from discovery data
|
|
*/
|
|
public static fromDiscovery(
|
|
data: {
|
|
id: string;
|
|
name: string;
|
|
address: string;
|
|
port?: number;
|
|
community?: string;
|
|
},
|
|
retryOptions?: IRetryOptions
|
|
): SnmpDevice {
|
|
const info: IDeviceInfo = {
|
|
id: data.id,
|
|
name: data.name,
|
|
type: 'snmp',
|
|
address: data.address,
|
|
port: data.port ?? 161,
|
|
status: 'unknown',
|
|
};
|
|
return new SnmpDevice(
|
|
info,
|
|
{ community: data.community ?? 'public' },
|
|
retryOptions
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Probe an IP address for SNMP device
|
|
*/
|
|
public static async probe(
|
|
address: string,
|
|
port: number = 161,
|
|
community: string = 'public',
|
|
timeout: number = 5000
|
|
): Promise<ISnmpDeviceInfo | null> {
|
|
const protocol = new SnmpProtocol(address, {
|
|
community,
|
|
port,
|
|
timeout,
|
|
retries: 0,
|
|
});
|
|
|
|
try {
|
|
const sysInfo = await protocol.getSystemInfo();
|
|
|
|
return {
|
|
id: `snmp:${address}:${port}`,
|
|
name: sysInfo.sysName || `SNMP Device at ${address}`,
|
|
type: 'snmp',
|
|
address,
|
|
port,
|
|
status: 'online',
|
|
sysDescr: sysInfo.sysDescr,
|
|
sysObjectID: sysInfo.sysObjectID,
|
|
sysUpTime: sysInfo.sysUpTime,
|
|
sysContact: sysInfo.sysContact || undefined,
|
|
sysName: sysInfo.sysName || undefined,
|
|
sysLocation: sysInfo.sysLocation || undefined,
|
|
};
|
|
} catch {
|
|
return null;
|
|
} finally {
|
|
protocol.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
export { SNMP_OIDS };
|