@ecobridge.xyz/devicemanager 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitea/workflows/default_nottags.yaml +66 -0
- package/.gitea/workflows/default_tags.yaml +124 -0
- package/.vscode/launch.json +11 -0
- package/.vscode/settings.json +26 -0
- package/changelog.md +91 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/device/device.classes.device.d.ts +205 -0
- package/dist_ts/device/device.classes.device.js +344 -0
- package/dist_ts/devicemanager.classes.devicemanager.d.ts +210 -0
- package/dist_ts/devicemanager.classes.devicemanager.js +835 -0
- package/dist_ts/discovery/discovery.classes.homeassistant.d.ts +101 -0
- package/dist_ts/discovery/discovery.classes.homeassistant.js +313 -0
- package/dist_ts/discovery/discovery.classes.mdns.d.ts +90 -0
- package/dist_ts/discovery/discovery.classes.mdns.js +291 -0
- package/dist_ts/discovery/discovery.classes.networkscanner.d.ts +64 -0
- package/dist_ts/discovery/discovery.classes.networkscanner.js +535 -0
- package/dist_ts/discovery/discovery.classes.ssdp.d.ts +112 -0
- package/dist_ts/discovery/discovery.classes.ssdp.js +255 -0
- package/dist_ts/factories/index.d.ts +190 -0
- package/dist_ts/factories/index.js +350 -0
- package/dist_ts/features/feature.abstract.d.ts +118 -0
- package/dist_ts/features/feature.abstract.js +172 -0
- package/dist_ts/features/feature.camera.d.ts +95 -0
- package/dist_ts/features/feature.camera.js +162 -0
- package/dist_ts/features/feature.climate.d.ts +174 -0
- package/dist_ts/features/feature.climate.js +328 -0
- package/dist_ts/features/feature.cover.d.ts +121 -0
- package/dist_ts/features/feature.cover.js +217 -0
- package/dist_ts/features/feature.fan.d.ts +127 -0
- package/dist_ts/features/feature.fan.js +235 -0
- package/dist_ts/features/feature.light.d.ts +156 -0
- package/dist_ts/features/feature.light.js +296 -0
- package/dist_ts/features/feature.lock.d.ts +103 -0
- package/dist_ts/features/feature.lock.js +170 -0
- package/dist_ts/features/feature.playback.d.ts +98 -0
- package/dist_ts/features/feature.playback.js +191 -0
- package/dist_ts/features/feature.power.d.ts +79 -0
- package/dist_ts/features/feature.power.js +173 -0
- package/dist_ts/features/feature.print.d.ts +78 -0
- package/dist_ts/features/feature.print.js +226 -0
- package/dist_ts/features/feature.scan.d.ts +79 -0
- package/dist_ts/features/feature.scan.js +315 -0
- package/dist_ts/features/feature.sensor.d.ts +95 -0
- package/dist_ts/features/feature.sensor.js +147 -0
- package/dist_ts/features/feature.snmp.d.ts +88 -0
- package/dist_ts/features/feature.snmp.js +175 -0
- package/dist_ts/features/feature.switch.d.ts +75 -0
- package/dist_ts/features/feature.switch.js +126 -0
- package/dist_ts/features/feature.volume.d.ts +104 -0
- package/dist_ts/features/feature.volume.js +186 -0
- package/dist_ts/features/index.d.ts +19 -0
- package/dist_ts/features/index.js +23 -0
- package/dist_ts/helpers/helpers.iprange.d.ts +35 -0
- package/dist_ts/helpers/helpers.iprange.js +151 -0
- package/dist_ts/helpers/helpers.retry.d.ts +25 -0
- package/dist_ts/helpers/helpers.retry.js +69 -0
- package/dist_ts/index.d.ts +15 -0
- package/dist_ts/index.js +40 -0
- package/dist_ts/interfaces/feature.interfaces.d.ts +255 -0
- package/dist_ts/interfaces/feature.interfaces.js +6 -0
- package/dist_ts/interfaces/homeassistant.interfaces.d.ts +550 -0
- package/dist_ts/interfaces/homeassistant.interfaces.js +111 -0
- package/dist_ts/interfaces/index.d.ts +330 -0
- package/dist_ts/interfaces/index.js +16 -0
- package/dist_ts/interfaces/smarthome.interfaces.d.ts +282 -0
- package/dist_ts/interfaces/smarthome.interfaces.js +7 -0
- package/dist_ts/paths.d.ts +1 -0
- package/dist_ts/paths.js +3 -0
- package/dist_ts/plugins.d.ts +23 -0
- package/dist_ts/plugins.js +30 -0
- package/dist_ts/protocols/index.d.ts +12 -0
- package/dist_ts/protocols/index.js +21 -0
- package/dist_ts/protocols/protocol.escl.d.ts +58 -0
- package/dist_ts/protocols/protocol.escl.js +364 -0
- package/dist_ts/protocols/protocol.homeassistant.d.ts +248 -0
- package/dist_ts/protocols/protocol.homeassistant.js +611 -0
- package/dist_ts/protocols/protocol.ipp.d.ts +45 -0
- package/dist_ts/protocols/protocol.ipp.js +284 -0
- package/dist_ts/protocols/protocol.nut.d.ts +160 -0
- package/dist_ts/protocols/protocol.nut.js +364 -0
- package/dist_ts/protocols/protocol.sane.d.ts +104 -0
- package/dist_ts/protocols/protocol.sane.js +597 -0
- package/dist_ts/protocols/protocol.snmp.d.ts +133 -0
- package/dist_ts/protocols/protocol.snmp.js +333 -0
- package/dist_ts/protocols/protocol.upnp.d.ts +207 -0
- package/dist_ts/protocols/protocol.upnp.js +442 -0
- package/dist_ts/protocols/protocol.upssnmp.d.ts +160 -0
- package/dist_ts/protocols/protocol.upssnmp.js +263 -0
- package/npmextra.json +24 -0
- package/package.json +39 -0
- package/readme.hints.md +115 -0
- package/readme.md +624 -0
- package/test/test.ts +261 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/device/device.classes.device.ts +454 -0
- package/ts/devicemanager.classes.devicemanager.ts +1219 -0
- package/ts/discovery/discovery.classes.homeassistant.ts +376 -0
- package/ts/discovery/discovery.classes.mdns.ts +347 -0
- package/ts/discovery/discovery.classes.networkscanner.ts +648 -0
- package/ts/discovery/discovery.classes.ssdp.ts +357 -0
- package/ts/factories/index.ts +696 -0
- package/ts/features/feature.abstract.ts +251 -0
- package/ts/features/feature.camera.ts +214 -0
- package/ts/features/feature.climate.ts +407 -0
- package/ts/features/feature.cover.ts +278 -0
- package/ts/features/feature.fan.ts +296 -0
- package/ts/features/feature.light.ts +369 -0
- package/ts/features/feature.lock.ts +223 -0
- package/ts/features/feature.playback.ts +246 -0
- package/ts/features/feature.power.ts +231 -0
- package/ts/features/feature.print.ts +297 -0
- package/ts/features/feature.scan.ts +370 -0
- package/ts/features/feature.sensor.ts +202 -0
- package/ts/features/feature.snmp.ts +235 -0
- package/ts/features/feature.switch.ts +170 -0
- package/ts/features/feature.volume.ts +256 -0
- package/ts/features/index.ts +25 -0
- package/ts/helpers/helpers.iprange.ts +172 -0
- package/ts/helpers/helpers.retry.ts +100 -0
- package/ts/index.ts +165 -0
- package/ts/interfaces/feature.interfaces.ts +359 -0
- package/ts/interfaces/homeassistant.interfaces.ts +666 -0
- package/ts/interfaces/index.ts +421 -0
- package/ts/interfaces/smarthome.interfaces.ts +421 -0
- package/ts/paths.ts +5 -0
- package/ts/plugins.ts +41 -0
- package/ts/protocols/index.ts +59 -0
- package/ts/protocols/protocol.escl.ts +439 -0
- package/ts/protocols/protocol.homeassistant.ts +737 -0
- package/ts/protocols/protocol.ipp.ts +329 -0
- package/ts/protocols/protocol.nut.ts +471 -0
- package/ts/protocols/protocol.sane.ts +694 -0
- package/ts/protocols/protocol.snmp.ts +439 -0
- package/ts/protocols/protocol.upnp.ts +627 -0
- package/ts/protocols/protocol.upssnmp.ts +377 -0
- package/tsconfig.json +12 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Common SNMP OIDs (Object Identifiers)
|
|
5
|
+
*/
|
|
6
|
+
export const SNMP_OIDS = {
|
|
7
|
+
// System MIB (RFC 1213)
|
|
8
|
+
sysDescr: '1.3.6.1.2.1.1.1.0',
|
|
9
|
+
sysObjectID: '1.3.6.1.2.1.1.2.0',
|
|
10
|
+
sysUpTime: '1.3.6.1.2.1.1.3.0',
|
|
11
|
+
sysContact: '1.3.6.1.2.1.1.4.0',
|
|
12
|
+
sysName: '1.3.6.1.2.1.1.5.0',
|
|
13
|
+
sysLocation: '1.3.6.1.2.1.1.6.0',
|
|
14
|
+
sysServices: '1.3.6.1.2.1.1.7.0',
|
|
15
|
+
|
|
16
|
+
// IF-MIB - Interfaces
|
|
17
|
+
ifNumber: '1.3.6.1.2.1.2.1.0',
|
|
18
|
+
ifTable: '1.3.6.1.2.1.2.2',
|
|
19
|
+
|
|
20
|
+
// Host resources
|
|
21
|
+
hrSystemUptime: '1.3.6.1.2.1.25.1.1.0',
|
|
22
|
+
hrMemorySize: '1.3.6.1.2.1.25.2.2.0',
|
|
23
|
+
|
|
24
|
+
// UPS-MIB (RFC 1628)
|
|
25
|
+
upsIdentManufacturer: '1.3.6.1.2.1.33.1.1.1.0',
|
|
26
|
+
upsIdentModel: '1.3.6.1.2.1.33.1.1.2.0',
|
|
27
|
+
upsBatteryStatus: '1.3.6.1.2.1.33.1.2.1.0',
|
|
28
|
+
upsSecondsOnBattery: '1.3.6.1.2.1.33.1.2.2.0',
|
|
29
|
+
upsEstimatedMinutesRemaining: '1.3.6.1.2.1.33.1.2.3.0',
|
|
30
|
+
upsEstimatedChargeRemaining: '1.3.6.1.2.1.33.1.2.4.0',
|
|
31
|
+
upsBatteryVoltage: '1.3.6.1.2.1.33.1.2.5.0',
|
|
32
|
+
upsInputFrequency: '1.3.6.1.2.1.33.1.3.3.1.2',
|
|
33
|
+
upsInputVoltage: '1.3.6.1.2.1.33.1.3.3.1.3',
|
|
34
|
+
upsOutputSource: '1.3.6.1.2.1.33.1.4.1.0',
|
|
35
|
+
upsOutputFrequency: '1.3.6.1.2.1.33.1.4.2.0',
|
|
36
|
+
upsOutputVoltage: '1.3.6.1.2.1.33.1.4.4.1.2',
|
|
37
|
+
upsOutputCurrent: '1.3.6.1.2.1.33.1.4.4.1.3',
|
|
38
|
+
upsOutputPower: '1.3.6.1.2.1.33.1.4.4.1.4',
|
|
39
|
+
upsOutputPercentLoad: '1.3.6.1.2.1.33.1.4.4.1.5',
|
|
40
|
+
|
|
41
|
+
// Printer MIB
|
|
42
|
+
prtGeneralPrinterName: '1.3.6.1.2.1.43.5.1.1.16.1',
|
|
43
|
+
prtMarkerSuppliesLevel: '1.3.6.1.2.1.43.11.1.1.9',
|
|
44
|
+
prtMarkerSuppliesMaxCapacity: '1.3.6.1.2.1.43.11.1.1.8',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* SNMP value types
|
|
49
|
+
*/
|
|
50
|
+
export type TSnmpValueType =
|
|
51
|
+
| 'OctetString'
|
|
52
|
+
| 'Integer'
|
|
53
|
+
| 'Counter'
|
|
54
|
+
| 'Counter32'
|
|
55
|
+
| 'Counter64'
|
|
56
|
+
| 'Gauge'
|
|
57
|
+
| 'Gauge32'
|
|
58
|
+
| 'TimeTicks'
|
|
59
|
+
| 'IpAddress'
|
|
60
|
+
| 'ObjectIdentifier'
|
|
61
|
+
| 'Null'
|
|
62
|
+
| 'Opaque';
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* SNMP varbind (variable binding)
|
|
66
|
+
*/
|
|
67
|
+
export interface ISnmpVarbind {
|
|
68
|
+
oid: string;
|
|
69
|
+
type: TSnmpValueType;
|
|
70
|
+
value: unknown;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* SNMP session options
|
|
75
|
+
*/
|
|
76
|
+
export interface ISnmpOptions {
|
|
77
|
+
/** Community string (v1/v2c) or username (v3) */
|
|
78
|
+
community?: string;
|
|
79
|
+
/** SNMP version: 1, 2 (v2c), or 3 */
|
|
80
|
+
version?: 1 | 2 | 3;
|
|
81
|
+
/** Request timeout in milliseconds */
|
|
82
|
+
timeout?: number;
|
|
83
|
+
/** Number of retries */
|
|
84
|
+
retries?: number;
|
|
85
|
+
/** Port (default: 161) */
|
|
86
|
+
port?: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const DEFAULT_OPTIONS: Required<ISnmpOptions> = {
|
|
90
|
+
community: 'public',
|
|
91
|
+
version: 2,
|
|
92
|
+
timeout: 5000,
|
|
93
|
+
retries: 1,
|
|
94
|
+
port: 161,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* SNMP Protocol handler using net-snmp
|
|
99
|
+
*/
|
|
100
|
+
export class SnmpProtocol {
|
|
101
|
+
private session: ReturnType<typeof plugins.netSnmp.createSession> | null = null;
|
|
102
|
+
private address: string;
|
|
103
|
+
private options: Required<ISnmpOptions>;
|
|
104
|
+
|
|
105
|
+
constructor(address: string, options?: ISnmpOptions) {
|
|
106
|
+
this.address = address;
|
|
107
|
+
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Create SNMP session
|
|
112
|
+
*/
|
|
113
|
+
private getSession(): ReturnType<typeof plugins.netSnmp.createSession> {
|
|
114
|
+
if (!this.session) {
|
|
115
|
+
const snmpVersion =
|
|
116
|
+
this.options.version === 1
|
|
117
|
+
? plugins.netSnmp.Version1
|
|
118
|
+
: plugins.netSnmp.Version2c;
|
|
119
|
+
|
|
120
|
+
this.session = plugins.netSnmp.createSession(this.address, this.options.community, {
|
|
121
|
+
port: this.options.port,
|
|
122
|
+
retries: this.options.retries,
|
|
123
|
+
timeout: this.options.timeout,
|
|
124
|
+
version: snmpVersion,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return this.session;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Close SNMP session
|
|
132
|
+
*/
|
|
133
|
+
public close(): void {
|
|
134
|
+
if (this.session) {
|
|
135
|
+
this.session.close();
|
|
136
|
+
this.session = null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* GET operation - retrieve a single OID value
|
|
142
|
+
*/
|
|
143
|
+
public async get(oid: string): Promise<ISnmpVarbind> {
|
|
144
|
+
return new Promise((resolve, reject) => {
|
|
145
|
+
const session = this.getSession();
|
|
146
|
+
|
|
147
|
+
session.get([oid], (error: Error | null, varbinds: unknown[]) => {
|
|
148
|
+
if (error) {
|
|
149
|
+
reject(error);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (varbinds.length === 0) {
|
|
154
|
+
reject(new Error(`No response for OID ${oid}`));
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const vb = varbinds[0] as { oid: string; type: number; value: unknown };
|
|
159
|
+
|
|
160
|
+
if (plugins.netSnmp.isVarbindError(vb)) {
|
|
161
|
+
reject(new Error(`SNMP error for ${oid}: ${plugins.netSnmp.varbindError(vb)}`));
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
resolve(this.parseVarbind(vb));
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* GET operation - retrieve multiple OID values
|
|
172
|
+
*/
|
|
173
|
+
public async getMultiple(oids: string[]): Promise<ISnmpVarbind[]> {
|
|
174
|
+
return new Promise((resolve, reject) => {
|
|
175
|
+
const session = this.getSession();
|
|
176
|
+
|
|
177
|
+
session.get(oids, (error: Error | null, varbinds: unknown[]) => {
|
|
178
|
+
if (error) {
|
|
179
|
+
reject(error);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const results: ISnmpVarbind[] = [];
|
|
184
|
+
for (const vb of varbinds) {
|
|
185
|
+
const varbind = vb as { oid: string; type: number; value: unknown };
|
|
186
|
+
if (!plugins.netSnmp.isVarbindError(varbind)) {
|
|
187
|
+
results.push(this.parseVarbind(varbind));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
resolve(results);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* GETNEXT operation - get the next OID in the MIB tree
|
|
198
|
+
*/
|
|
199
|
+
public async getNext(oid: string): Promise<ISnmpVarbind> {
|
|
200
|
+
return new Promise((resolve, reject) => {
|
|
201
|
+
const session = this.getSession();
|
|
202
|
+
|
|
203
|
+
session.getNext([oid], (error: Error | null, varbinds: unknown[]) => {
|
|
204
|
+
if (error) {
|
|
205
|
+
reject(error);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (varbinds.length === 0) {
|
|
210
|
+
reject(new Error(`No response for GETNEXT ${oid}`));
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const vb = varbinds[0] as { oid: string; type: number; value: unknown };
|
|
215
|
+
|
|
216
|
+
if (plugins.netSnmp.isVarbindError(vb)) {
|
|
217
|
+
reject(new Error(`SNMP error for ${oid}: ${plugins.netSnmp.varbindError(vb)}`));
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
resolve(this.parseVarbind(vb));
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* GETBULK operation (v2c/v3 only) - efficient retrieval of table rows
|
|
228
|
+
*/
|
|
229
|
+
public async getBulk(
|
|
230
|
+
oids: string[],
|
|
231
|
+
nonRepeaters: number = 0,
|
|
232
|
+
maxRepetitions: number = 20
|
|
233
|
+
): Promise<ISnmpVarbind[]> {
|
|
234
|
+
if (this.options.version === 1) {
|
|
235
|
+
throw new Error('GETBULK is not supported in SNMPv1');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return new Promise((resolve, reject) => {
|
|
239
|
+
const session = this.getSession();
|
|
240
|
+
|
|
241
|
+
session.getBulk(oids, nonRepeaters, maxRepetitions, (error: Error | null, varbinds: unknown[]) => {
|
|
242
|
+
if (error) {
|
|
243
|
+
reject(error);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const results: ISnmpVarbind[] = [];
|
|
248
|
+
for (const vb of varbinds) {
|
|
249
|
+
const varbind = vb as { oid: string; type: number; value: unknown };
|
|
250
|
+
if (!plugins.netSnmp.isVarbindError(varbind)) {
|
|
251
|
+
results.push(this.parseVarbind(varbind));
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
resolve(results);
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Walk operation - retrieve all OIDs under a tree
|
|
262
|
+
*/
|
|
263
|
+
public async walk(baseOid: string): Promise<ISnmpVarbind[]> {
|
|
264
|
+
return new Promise((resolve, reject) => {
|
|
265
|
+
const session = this.getSession();
|
|
266
|
+
const results: ISnmpVarbind[] = [];
|
|
267
|
+
|
|
268
|
+
session.walk(
|
|
269
|
+
baseOid,
|
|
270
|
+
20, // maxRepetitions
|
|
271
|
+
(varbinds: unknown[]) => {
|
|
272
|
+
for (const vb of varbinds) {
|
|
273
|
+
const varbind = vb as { oid: string; type: number; value: unknown };
|
|
274
|
+
if (!plugins.netSnmp.isVarbindError(varbind)) {
|
|
275
|
+
results.push(this.parseVarbind(varbind));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
(error: Error | null) => {
|
|
280
|
+
if (error) {
|
|
281
|
+
reject(error);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
resolve(results);
|
|
285
|
+
}
|
|
286
|
+
);
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* SET operation - set an OID value
|
|
292
|
+
*/
|
|
293
|
+
public async set(oid: string, type: TSnmpValueType, value: unknown): Promise<ISnmpVarbind> {
|
|
294
|
+
return new Promise((resolve, reject) => {
|
|
295
|
+
const session = this.getSession();
|
|
296
|
+
|
|
297
|
+
const snmpType = this.getSnmpType(type);
|
|
298
|
+
const varbind = {
|
|
299
|
+
oid,
|
|
300
|
+
type: snmpType,
|
|
301
|
+
value,
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
session.set([varbind], (error: Error | null, varbinds: unknown[]) => {
|
|
305
|
+
if (error) {
|
|
306
|
+
reject(error);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (varbinds.length === 0) {
|
|
311
|
+
reject(new Error(`No response for SET ${oid}`));
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const vb = varbinds[0] as { oid: string; type: number; value: unknown };
|
|
316
|
+
|
|
317
|
+
if (plugins.netSnmp.isVarbindError(vb)) {
|
|
318
|
+
reject(new Error(`SNMP error for ${oid}: ${plugins.netSnmp.varbindError(vb)}`));
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
resolve(this.parseVarbind(vb));
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Get system information
|
|
329
|
+
*/
|
|
330
|
+
public async getSystemInfo(): Promise<{
|
|
331
|
+
sysDescr: string;
|
|
332
|
+
sysObjectID: string;
|
|
333
|
+
sysUpTime: number;
|
|
334
|
+
sysContact: string;
|
|
335
|
+
sysName: string;
|
|
336
|
+
sysLocation: string;
|
|
337
|
+
}> {
|
|
338
|
+
const oids = [
|
|
339
|
+
SNMP_OIDS.sysDescr,
|
|
340
|
+
SNMP_OIDS.sysObjectID,
|
|
341
|
+
SNMP_OIDS.sysUpTime,
|
|
342
|
+
SNMP_OIDS.sysContact,
|
|
343
|
+
SNMP_OIDS.sysName,
|
|
344
|
+
SNMP_OIDS.sysLocation,
|
|
345
|
+
];
|
|
346
|
+
|
|
347
|
+
const varbinds = await this.getMultiple(oids);
|
|
348
|
+
|
|
349
|
+
const getValue = (oid: string): unknown => {
|
|
350
|
+
const vb = varbinds.find((v) => v.oid === oid);
|
|
351
|
+
return vb?.value;
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
sysDescr: String(getValue(SNMP_OIDS.sysDescr) || ''),
|
|
356
|
+
sysObjectID: String(getValue(SNMP_OIDS.sysObjectID) || ''),
|
|
357
|
+
sysUpTime: Number(getValue(SNMP_OIDS.sysUpTime) || 0),
|
|
358
|
+
sysContact: String(getValue(SNMP_OIDS.sysContact) || ''),
|
|
359
|
+
sysName: String(getValue(SNMP_OIDS.sysName) || ''),
|
|
360
|
+
sysLocation: String(getValue(SNMP_OIDS.sysLocation) || ''),
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Check if device is reachable via SNMP
|
|
366
|
+
*/
|
|
367
|
+
public async isReachable(): Promise<boolean> {
|
|
368
|
+
try {
|
|
369
|
+
await this.get(SNMP_OIDS.sysDescr);
|
|
370
|
+
return true;
|
|
371
|
+
} catch {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Parse varbind to our format
|
|
378
|
+
*/
|
|
379
|
+
private parseVarbind(vb: { oid: string; type: number; value: unknown }): ISnmpVarbind {
|
|
380
|
+
return {
|
|
381
|
+
oid: vb.oid,
|
|
382
|
+
type: this.getTypeName(vb.type),
|
|
383
|
+
value: this.parseValue(vb.type, vb.value),
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Get type name from SNMP type number
|
|
389
|
+
*/
|
|
390
|
+
private getTypeName(type: number): TSnmpValueType {
|
|
391
|
+
const typeMap: Record<number, TSnmpValueType> = {
|
|
392
|
+
[plugins.netSnmp.ObjectType.OctetString]: 'OctetString',
|
|
393
|
+
[plugins.netSnmp.ObjectType.Integer]: 'Integer',
|
|
394
|
+
[plugins.netSnmp.ObjectType.Counter]: 'Counter',
|
|
395
|
+
[plugins.netSnmp.ObjectType.Counter32]: 'Counter32',
|
|
396
|
+
[plugins.netSnmp.ObjectType.Counter64]: 'Counter64',
|
|
397
|
+
[plugins.netSnmp.ObjectType.Gauge]: 'Gauge',
|
|
398
|
+
[plugins.netSnmp.ObjectType.Gauge32]: 'Gauge32',
|
|
399
|
+
[plugins.netSnmp.ObjectType.TimeTicks]: 'TimeTicks',
|
|
400
|
+
[plugins.netSnmp.ObjectType.IpAddress]: 'IpAddress',
|
|
401
|
+
[plugins.netSnmp.ObjectType.OID]: 'ObjectIdentifier',
|
|
402
|
+
[plugins.netSnmp.ObjectType.Null]: 'Null',
|
|
403
|
+
[plugins.netSnmp.ObjectType.Opaque]: 'Opaque',
|
|
404
|
+
};
|
|
405
|
+
return typeMap[type] || 'OctetString';
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Get SNMP type number from type name
|
|
410
|
+
*/
|
|
411
|
+
private getSnmpType(type: TSnmpValueType): number {
|
|
412
|
+
const typeMap: Record<TSnmpValueType, number> = {
|
|
413
|
+
OctetString: plugins.netSnmp.ObjectType.OctetString,
|
|
414
|
+
Integer: plugins.netSnmp.ObjectType.Integer,
|
|
415
|
+
Counter: plugins.netSnmp.ObjectType.Counter,
|
|
416
|
+
Counter32: plugins.netSnmp.ObjectType.Counter32,
|
|
417
|
+
Counter64: plugins.netSnmp.ObjectType.Counter64,
|
|
418
|
+
Gauge: plugins.netSnmp.ObjectType.Gauge,
|
|
419
|
+
Gauge32: plugins.netSnmp.ObjectType.Gauge32,
|
|
420
|
+
TimeTicks: plugins.netSnmp.ObjectType.TimeTicks,
|
|
421
|
+
IpAddress: plugins.netSnmp.ObjectType.IpAddress,
|
|
422
|
+
ObjectIdentifier: plugins.netSnmp.ObjectType.OID,
|
|
423
|
+
Null: plugins.netSnmp.ObjectType.Null,
|
|
424
|
+
Opaque: plugins.netSnmp.ObjectType.Opaque,
|
|
425
|
+
};
|
|
426
|
+
return typeMap[type];
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Parse value based on type
|
|
431
|
+
*/
|
|
432
|
+
private parseValue(type: number, value: unknown): unknown {
|
|
433
|
+
// OctetString - convert Buffer to string
|
|
434
|
+
if (type === plugins.netSnmp.ObjectType.OctetString && Buffer.isBuffer(value)) {
|
|
435
|
+
return value.toString('utf8');
|
|
436
|
+
}
|
|
437
|
+
return value;
|
|
438
|
+
}
|
|
439
|
+
}
|