@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.
Files changed (137) hide show
  1. package/.gitea/workflows/default_nottags.yaml +66 -0
  2. package/.gitea/workflows/default_tags.yaml +124 -0
  3. package/.vscode/launch.json +11 -0
  4. package/.vscode/settings.json +26 -0
  5. package/changelog.md +91 -0
  6. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  7. package/dist_ts/00_commitinfo_data.js +9 -0
  8. package/dist_ts/device/device.classes.device.d.ts +205 -0
  9. package/dist_ts/device/device.classes.device.js +344 -0
  10. package/dist_ts/devicemanager.classes.devicemanager.d.ts +210 -0
  11. package/dist_ts/devicemanager.classes.devicemanager.js +835 -0
  12. package/dist_ts/discovery/discovery.classes.homeassistant.d.ts +101 -0
  13. package/dist_ts/discovery/discovery.classes.homeassistant.js +313 -0
  14. package/dist_ts/discovery/discovery.classes.mdns.d.ts +90 -0
  15. package/dist_ts/discovery/discovery.classes.mdns.js +291 -0
  16. package/dist_ts/discovery/discovery.classes.networkscanner.d.ts +64 -0
  17. package/dist_ts/discovery/discovery.classes.networkscanner.js +535 -0
  18. package/dist_ts/discovery/discovery.classes.ssdp.d.ts +112 -0
  19. package/dist_ts/discovery/discovery.classes.ssdp.js +255 -0
  20. package/dist_ts/factories/index.d.ts +190 -0
  21. package/dist_ts/factories/index.js +350 -0
  22. package/dist_ts/features/feature.abstract.d.ts +118 -0
  23. package/dist_ts/features/feature.abstract.js +172 -0
  24. package/dist_ts/features/feature.camera.d.ts +95 -0
  25. package/dist_ts/features/feature.camera.js +162 -0
  26. package/dist_ts/features/feature.climate.d.ts +174 -0
  27. package/dist_ts/features/feature.climate.js +328 -0
  28. package/dist_ts/features/feature.cover.d.ts +121 -0
  29. package/dist_ts/features/feature.cover.js +217 -0
  30. package/dist_ts/features/feature.fan.d.ts +127 -0
  31. package/dist_ts/features/feature.fan.js +235 -0
  32. package/dist_ts/features/feature.light.d.ts +156 -0
  33. package/dist_ts/features/feature.light.js +296 -0
  34. package/dist_ts/features/feature.lock.d.ts +103 -0
  35. package/dist_ts/features/feature.lock.js +170 -0
  36. package/dist_ts/features/feature.playback.d.ts +98 -0
  37. package/dist_ts/features/feature.playback.js +191 -0
  38. package/dist_ts/features/feature.power.d.ts +79 -0
  39. package/dist_ts/features/feature.power.js +173 -0
  40. package/dist_ts/features/feature.print.d.ts +78 -0
  41. package/dist_ts/features/feature.print.js +226 -0
  42. package/dist_ts/features/feature.scan.d.ts +79 -0
  43. package/dist_ts/features/feature.scan.js +315 -0
  44. package/dist_ts/features/feature.sensor.d.ts +95 -0
  45. package/dist_ts/features/feature.sensor.js +147 -0
  46. package/dist_ts/features/feature.snmp.d.ts +88 -0
  47. package/dist_ts/features/feature.snmp.js +175 -0
  48. package/dist_ts/features/feature.switch.d.ts +75 -0
  49. package/dist_ts/features/feature.switch.js +126 -0
  50. package/dist_ts/features/feature.volume.d.ts +104 -0
  51. package/dist_ts/features/feature.volume.js +186 -0
  52. package/dist_ts/features/index.d.ts +19 -0
  53. package/dist_ts/features/index.js +23 -0
  54. package/dist_ts/helpers/helpers.iprange.d.ts +35 -0
  55. package/dist_ts/helpers/helpers.iprange.js +151 -0
  56. package/dist_ts/helpers/helpers.retry.d.ts +25 -0
  57. package/dist_ts/helpers/helpers.retry.js +69 -0
  58. package/dist_ts/index.d.ts +15 -0
  59. package/dist_ts/index.js +40 -0
  60. package/dist_ts/interfaces/feature.interfaces.d.ts +255 -0
  61. package/dist_ts/interfaces/feature.interfaces.js +6 -0
  62. package/dist_ts/interfaces/homeassistant.interfaces.d.ts +550 -0
  63. package/dist_ts/interfaces/homeassistant.interfaces.js +111 -0
  64. package/dist_ts/interfaces/index.d.ts +330 -0
  65. package/dist_ts/interfaces/index.js +16 -0
  66. package/dist_ts/interfaces/smarthome.interfaces.d.ts +282 -0
  67. package/dist_ts/interfaces/smarthome.interfaces.js +7 -0
  68. package/dist_ts/paths.d.ts +1 -0
  69. package/dist_ts/paths.js +3 -0
  70. package/dist_ts/plugins.d.ts +23 -0
  71. package/dist_ts/plugins.js +30 -0
  72. package/dist_ts/protocols/index.d.ts +12 -0
  73. package/dist_ts/protocols/index.js +21 -0
  74. package/dist_ts/protocols/protocol.escl.d.ts +58 -0
  75. package/dist_ts/protocols/protocol.escl.js +364 -0
  76. package/dist_ts/protocols/protocol.homeassistant.d.ts +248 -0
  77. package/dist_ts/protocols/protocol.homeassistant.js +611 -0
  78. package/dist_ts/protocols/protocol.ipp.d.ts +45 -0
  79. package/dist_ts/protocols/protocol.ipp.js +284 -0
  80. package/dist_ts/protocols/protocol.nut.d.ts +160 -0
  81. package/dist_ts/protocols/protocol.nut.js +364 -0
  82. package/dist_ts/protocols/protocol.sane.d.ts +104 -0
  83. package/dist_ts/protocols/protocol.sane.js +597 -0
  84. package/dist_ts/protocols/protocol.snmp.d.ts +133 -0
  85. package/dist_ts/protocols/protocol.snmp.js +333 -0
  86. package/dist_ts/protocols/protocol.upnp.d.ts +207 -0
  87. package/dist_ts/protocols/protocol.upnp.js +442 -0
  88. package/dist_ts/protocols/protocol.upssnmp.d.ts +160 -0
  89. package/dist_ts/protocols/protocol.upssnmp.js +263 -0
  90. package/npmextra.json +24 -0
  91. package/package.json +39 -0
  92. package/readme.hints.md +115 -0
  93. package/readme.md +624 -0
  94. package/test/test.ts +261 -0
  95. package/ts/00_commitinfo_data.ts +8 -0
  96. package/ts/device/device.classes.device.ts +454 -0
  97. package/ts/devicemanager.classes.devicemanager.ts +1219 -0
  98. package/ts/discovery/discovery.classes.homeassistant.ts +376 -0
  99. package/ts/discovery/discovery.classes.mdns.ts +347 -0
  100. package/ts/discovery/discovery.classes.networkscanner.ts +648 -0
  101. package/ts/discovery/discovery.classes.ssdp.ts +357 -0
  102. package/ts/factories/index.ts +696 -0
  103. package/ts/features/feature.abstract.ts +251 -0
  104. package/ts/features/feature.camera.ts +214 -0
  105. package/ts/features/feature.climate.ts +407 -0
  106. package/ts/features/feature.cover.ts +278 -0
  107. package/ts/features/feature.fan.ts +296 -0
  108. package/ts/features/feature.light.ts +369 -0
  109. package/ts/features/feature.lock.ts +223 -0
  110. package/ts/features/feature.playback.ts +246 -0
  111. package/ts/features/feature.power.ts +231 -0
  112. package/ts/features/feature.print.ts +297 -0
  113. package/ts/features/feature.scan.ts +370 -0
  114. package/ts/features/feature.sensor.ts +202 -0
  115. package/ts/features/feature.snmp.ts +235 -0
  116. package/ts/features/feature.switch.ts +170 -0
  117. package/ts/features/feature.volume.ts +256 -0
  118. package/ts/features/index.ts +25 -0
  119. package/ts/helpers/helpers.iprange.ts +172 -0
  120. package/ts/helpers/helpers.retry.ts +100 -0
  121. package/ts/index.ts +165 -0
  122. package/ts/interfaces/feature.interfaces.ts +359 -0
  123. package/ts/interfaces/homeassistant.interfaces.ts +666 -0
  124. package/ts/interfaces/index.ts +421 -0
  125. package/ts/interfaces/smarthome.interfaces.ts +421 -0
  126. package/ts/paths.ts +5 -0
  127. package/ts/plugins.ts +41 -0
  128. package/ts/protocols/index.ts +59 -0
  129. package/ts/protocols/protocol.escl.ts +439 -0
  130. package/ts/protocols/protocol.homeassistant.ts +737 -0
  131. package/ts/protocols/protocol.ipp.ts +329 -0
  132. package/ts/protocols/protocol.nut.ts +471 -0
  133. package/ts/protocols/protocol.sane.ts +694 -0
  134. package/ts/protocols/protocol.snmp.ts +439 -0
  135. package/ts/protocols/protocol.upnp.ts +627 -0
  136. package/ts/protocols/protocol.upssnmp.ts +377 -0
  137. package/tsconfig.json +12 -0
@@ -0,0 +1,471 @@
1
+ import * as plugins from '../plugins.js';
2
+
3
+ /**
4
+ * NUT Protocol variable definitions
5
+ */
6
+ export const NUT_VARIABLES = {
7
+ // Device info
8
+ deviceMfr: 'device.mfr',
9
+ deviceModel: 'device.model',
10
+ deviceSerial: 'device.serial',
11
+ deviceType: 'device.type',
12
+
13
+ // UPS status
14
+ upsStatus: 'ups.status',
15
+ upsAlarm: 'ups.alarm',
16
+ upsTime: 'ups.time',
17
+ upsLoad: 'ups.load',
18
+ upsTemperature: 'ups.temperature',
19
+
20
+ // Battery
21
+ batteryCharge: 'battery.charge',
22
+ batteryRuntime: 'battery.runtime',
23
+ batteryVoltage: 'battery.voltage',
24
+ batteryVoltageNominal: 'battery.voltage.nominal',
25
+ batteryType: 'battery.type',
26
+ batteryDate: 'battery.date',
27
+ batteryTemperature: 'battery.temperature',
28
+
29
+ // Input
30
+ inputVoltage: 'input.voltage',
31
+ inputVoltageNominal: 'input.voltage.nominal',
32
+ inputFrequency: 'input.frequency',
33
+ inputFrequencyNominal: 'input.frequency.nominal',
34
+ inputTransferHigh: 'input.transfer.high',
35
+ inputTransferLow: 'input.transfer.low',
36
+
37
+ // Output
38
+ outputVoltage: 'output.voltage',
39
+ outputVoltageNominal: 'output.voltage.nominal',
40
+ outputFrequency: 'output.frequency',
41
+ outputCurrent: 'output.current',
42
+ };
43
+
44
+ /**
45
+ * NUT instant commands
46
+ */
47
+ export const NUT_COMMANDS = {
48
+ testBatteryStart: 'test.battery.start',
49
+ testBatteryStartQuick: 'test.battery.start.quick',
50
+ testBatteryStartDeep: 'test.battery.start.deep',
51
+ testBatteryStop: 'test.battery.stop',
52
+ calibrateStart: 'calibrate.start',
53
+ calibrateStop: 'calibrate.stop',
54
+ shutdown: 'shutdown.return',
55
+ shutdownStayOff: 'shutdown.stayoff',
56
+ shutdownStop: 'shutdown.stop',
57
+ shutdownReboot: 'shutdown.reboot',
58
+ beeperEnable: 'beeper.enable',
59
+ beeperDisable: 'beeper.disable',
60
+ beeperMute: 'beeper.mute',
61
+ beeperToggle: 'beeper.toggle',
62
+ loadOff: 'load.off',
63
+ loadOn: 'load.on',
64
+ };
65
+
66
+ /**
67
+ * UPS status flags from NUT
68
+ */
69
+ export type TNutStatusFlag =
70
+ | 'OL' // Online (on utility power)
71
+ | 'OB' // On battery
72
+ | 'LB' // Low battery
73
+ | 'HB' // High battery
74
+ | 'RB' // Replace battery
75
+ | 'CHRG' // Charging
76
+ | 'DISCHRG' // Discharging
77
+ | 'BYPASS' // On bypass
78
+ | 'CAL' // Calibrating
79
+ | 'OFF' // Offline
80
+ | 'OVER' // Overloaded
81
+ | 'TRIM' // Trimming voltage
82
+ | 'BOOST' // Boosting voltage
83
+ | 'FSD'; // Forced shutdown
84
+
85
+ /**
86
+ * NUT UPS information
87
+ */
88
+ export interface INutUpsInfo {
89
+ name: string;
90
+ description: string;
91
+ }
92
+
93
+ /**
94
+ * NUT variable
95
+ */
96
+ export interface INutVariable {
97
+ name: string;
98
+ value: string;
99
+ }
100
+
101
+ /**
102
+ * NUT Protocol handler for Network UPS Tools
103
+ * TCP-based text protocol on port 3493
104
+ */
105
+ export class NutProtocol {
106
+ private socket: plugins.net.Socket | null = null;
107
+ private address: string;
108
+ private port: number;
109
+ private connected: boolean = false;
110
+ private responseBuffer: string = '';
111
+ private responseResolver: ((value: string[]) => void) | null = null;
112
+ private responseRejecter: ((error: Error) => void) | null = null;
113
+
114
+ constructor(address: string, port: number = 3493) {
115
+ this.address = address;
116
+ this.port = port;
117
+ }
118
+
119
+ /**
120
+ * Connect to NUT server
121
+ */
122
+ public async connect(): Promise<void> {
123
+ if (this.connected) {
124
+ return;
125
+ }
126
+
127
+ return new Promise((resolve, reject) => {
128
+ this.socket = new plugins.net.Socket();
129
+
130
+ const timeout = setTimeout(() => {
131
+ if (this.socket) {
132
+ this.socket.destroy();
133
+ this.socket = null;
134
+ }
135
+ reject(new Error(`Connection timeout to ${this.address}:${this.port}`));
136
+ }, 5000);
137
+
138
+ this.socket.on('connect', () => {
139
+ clearTimeout(timeout);
140
+ this.connected = true;
141
+ resolve();
142
+ });
143
+
144
+ this.socket.on('error', (err) => {
145
+ clearTimeout(timeout);
146
+ this.connected = false;
147
+ if (this.responseRejecter) {
148
+ this.responseRejecter(err);
149
+ this.responseRejecter = null;
150
+ this.responseResolver = null;
151
+ }
152
+ reject(err);
153
+ });
154
+
155
+ this.socket.on('data', (data: Buffer) => {
156
+ this.handleData(data);
157
+ });
158
+
159
+ this.socket.on('close', () => {
160
+ this.connected = false;
161
+ if (this.responseRejecter) {
162
+ this.responseRejecter(new Error('Connection closed'));
163
+ this.responseRejecter = null;
164
+ this.responseResolver = null;
165
+ }
166
+ });
167
+
168
+ this.socket.connect(this.port, this.address);
169
+ });
170
+ }
171
+
172
+ /**
173
+ * Disconnect from NUT server
174
+ */
175
+ public async disconnect(): Promise<void> {
176
+ if (!this.connected || !this.socket) {
177
+ return;
178
+ }
179
+
180
+ try {
181
+ await this.sendCommand('LOGOUT');
182
+ } catch {
183
+ // Ignore logout errors
184
+ }
185
+
186
+ this.socket.destroy();
187
+ this.socket = null;
188
+ this.connected = false;
189
+ }
190
+
191
+ /**
192
+ * Check if connected
193
+ */
194
+ public get isConnected(): boolean {
195
+ return this.connected;
196
+ }
197
+
198
+ /**
199
+ * Handle incoming data
200
+ */
201
+ private handleData(data: Buffer): void {
202
+ this.responseBuffer += data.toString();
203
+
204
+ // Check for complete response (ends with newline)
205
+ const lines = this.responseBuffer.split('\n');
206
+
207
+ // Check if we have a complete response
208
+ if (this.responseBuffer.endsWith('\n')) {
209
+ const responseLines = lines.filter((l) => l.trim().length > 0);
210
+ this.responseBuffer = '';
211
+
212
+ if (this.responseResolver) {
213
+ this.responseResolver(responseLines);
214
+ this.responseResolver = null;
215
+ this.responseRejecter = null;
216
+ }
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Send command and get response
222
+ */
223
+ private async sendCommand(command: string): Promise<string[]> {
224
+ if (!this.socket || !this.connected) {
225
+ throw new Error('Not connected to NUT server');
226
+ }
227
+
228
+ return new Promise((resolve, reject) => {
229
+ this.responseResolver = resolve;
230
+ this.responseRejecter = reject;
231
+
232
+ const timeout = setTimeout(() => {
233
+ this.responseResolver = null;
234
+ this.responseRejecter = null;
235
+ reject(new Error(`Command timeout: ${command}`));
236
+ }, 10000);
237
+
238
+ this.responseResolver = (lines) => {
239
+ clearTimeout(timeout);
240
+ resolve(lines);
241
+ };
242
+
243
+ this.responseRejecter = (err) => {
244
+ clearTimeout(timeout);
245
+ reject(err);
246
+ };
247
+
248
+ this.socket!.write(`${command}\n`);
249
+ });
250
+ }
251
+
252
+ /**
253
+ * List available UPS devices
254
+ */
255
+ public async listUps(): Promise<INutUpsInfo[]> {
256
+ await this.ensureConnected();
257
+ const response = await this.sendCommand('LIST UPS');
258
+
259
+ const upsList: INutUpsInfo[] = [];
260
+
261
+ for (const line of response) {
262
+ // Format: UPS <name> "<description>"
263
+ const match = line.match(/^UPS\s+(\S+)\s+"([^"]*)"/);
264
+ if (match) {
265
+ upsList.push({
266
+ name: match[1],
267
+ description: match[2],
268
+ });
269
+ }
270
+ }
271
+
272
+ return upsList;
273
+ }
274
+
275
+ /**
276
+ * Get all variables for a UPS
277
+ */
278
+ public async listVariables(upsName: string): Promise<INutVariable[]> {
279
+ await this.ensureConnected();
280
+ const response = await this.sendCommand(`LIST VAR ${upsName}`);
281
+
282
+ const variables: INutVariable[] = [];
283
+
284
+ for (const line of response) {
285
+ // Format: VAR <ups> <name> "<value>"
286
+ const match = line.match(/^VAR\s+\S+\s+(\S+)\s+"([^"]*)"/);
287
+ if (match) {
288
+ variables.push({
289
+ name: match[1],
290
+ value: match[2],
291
+ });
292
+ }
293
+ }
294
+
295
+ return variables;
296
+ }
297
+
298
+ /**
299
+ * Get a specific variable value
300
+ */
301
+ public async getVariable(upsName: string, varName: string): Promise<string | null> {
302
+ await this.ensureConnected();
303
+ const response = await this.sendCommand(`GET VAR ${upsName} ${varName}`);
304
+
305
+ for (const line of response) {
306
+ // Format: VAR <ups> <name> "<value>"
307
+ const match = line.match(/^VAR\s+\S+\s+\S+\s+"([^"]*)"/);
308
+ if (match) {
309
+ return match[1];
310
+ }
311
+ // Handle error responses
312
+ if (line.startsWith('ERR')) {
313
+ return null;
314
+ }
315
+ }
316
+
317
+ return null;
318
+ }
319
+
320
+ /**
321
+ * Get multiple variables at once
322
+ */
323
+ public async getVariables(upsName: string, varNames: string[]): Promise<Map<string, string>> {
324
+ const results = new Map<string, string>();
325
+
326
+ for (const varName of varNames) {
327
+ const value = await this.getVariable(upsName, varName);
328
+ if (value !== null) {
329
+ results.set(varName, value);
330
+ }
331
+ }
332
+
333
+ return results;
334
+ }
335
+
336
+ /**
337
+ * Execute an instant command
338
+ */
339
+ public async runCommand(upsName: string, command: string): Promise<boolean> {
340
+ await this.ensureConnected();
341
+ const response = await this.sendCommand(`INSTCMD ${upsName} ${command}`);
342
+
343
+ for (const line of response) {
344
+ if (line === 'OK') {
345
+ return true;
346
+ }
347
+ if (line.startsWith('ERR')) {
348
+ return false;
349
+ }
350
+ }
351
+
352
+ return false;
353
+ }
354
+
355
+ /**
356
+ * List available commands for a UPS
357
+ */
358
+ public async listCommands(upsName: string): Promise<string[]> {
359
+ await this.ensureConnected();
360
+ const response = await this.sendCommand(`LIST CMD ${upsName}`);
361
+
362
+ const commands: string[] = [];
363
+
364
+ for (const line of response) {
365
+ // Format: CMD <ups> <command>
366
+ const match = line.match(/^CMD\s+\S+\s+(\S+)/);
367
+ if (match) {
368
+ commands.push(match[1]);
369
+ }
370
+ }
371
+
372
+ return commands;
373
+ }
374
+
375
+ /**
376
+ * Parse UPS status string into flags
377
+ */
378
+ public parseStatus(statusString: string): TNutStatusFlag[] {
379
+ return statusString.split(/\s+/).filter((s) => s.length > 0) as TNutStatusFlag[];
380
+ }
381
+
382
+ /**
383
+ * Get comprehensive UPS status
384
+ */
385
+ public async getUpsStatus(upsName: string): Promise<{
386
+ status: TNutStatusFlag[];
387
+ batteryCharge: number;
388
+ batteryRuntime: number;
389
+ inputVoltage: number;
390
+ outputVoltage: number;
391
+ load: number;
392
+ }> {
393
+ const vars = await this.getVariables(upsName, [
394
+ NUT_VARIABLES.upsStatus,
395
+ NUT_VARIABLES.batteryCharge,
396
+ NUT_VARIABLES.batteryRuntime,
397
+ NUT_VARIABLES.inputVoltage,
398
+ NUT_VARIABLES.outputVoltage,
399
+ NUT_VARIABLES.upsLoad,
400
+ ]);
401
+
402
+ return {
403
+ status: this.parseStatus(vars.get(NUT_VARIABLES.upsStatus) || ''),
404
+ batteryCharge: parseFloat(vars.get(NUT_VARIABLES.batteryCharge) || '0'),
405
+ batteryRuntime: parseFloat(vars.get(NUT_VARIABLES.batteryRuntime) || '0'),
406
+ inputVoltage: parseFloat(vars.get(NUT_VARIABLES.inputVoltage) || '0'),
407
+ outputVoltage: parseFloat(vars.get(NUT_VARIABLES.outputVoltage) || '0'),
408
+ load: parseFloat(vars.get(NUT_VARIABLES.upsLoad) || '0'),
409
+ };
410
+ }
411
+
412
+ /**
413
+ * Get device information
414
+ */
415
+ public async getDeviceInfo(upsName: string): Promise<{
416
+ manufacturer: string;
417
+ model: string;
418
+ serial: string;
419
+ type: string;
420
+ }> {
421
+ const vars = await this.getVariables(upsName, [
422
+ NUT_VARIABLES.deviceMfr,
423
+ NUT_VARIABLES.deviceModel,
424
+ NUT_VARIABLES.deviceSerial,
425
+ NUT_VARIABLES.deviceType,
426
+ ]);
427
+
428
+ return {
429
+ manufacturer: vars.get(NUT_VARIABLES.deviceMfr) || '',
430
+ model: vars.get(NUT_VARIABLES.deviceModel) || '',
431
+ serial: vars.get(NUT_VARIABLES.deviceSerial) || '',
432
+ type: vars.get(NUT_VARIABLES.deviceType) || '',
433
+ };
434
+ }
435
+
436
+ /**
437
+ * Ensure connected before command
438
+ */
439
+ private async ensureConnected(): Promise<void> {
440
+ if (!this.connected) {
441
+ await this.connect();
442
+ }
443
+ }
444
+
445
+ /**
446
+ * Check if a NUT server is reachable
447
+ */
448
+ public static async probe(address: string, port: number = 3493, timeout: number = 3000): Promise<boolean> {
449
+ return new Promise((resolve) => {
450
+ const socket = new plugins.net.Socket();
451
+
452
+ const timer = setTimeout(() => {
453
+ socket.destroy();
454
+ resolve(false);
455
+ }, timeout);
456
+
457
+ socket.on('connect', () => {
458
+ clearTimeout(timer);
459
+ socket.destroy();
460
+ resolve(true);
461
+ });
462
+
463
+ socket.on('error', () => {
464
+ clearTimeout(timer);
465
+ resolve(false);
466
+ });
467
+
468
+ socket.connect(port, address);
469
+ });
470
+ }
471
+ }