@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,45 @@
|
|
|
1
|
+
import type { IPrinterCapabilities, IPrintOptions, IPrintJob } from '../interfaces/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* IPP protocol wrapper using the ipp npm package
|
|
4
|
+
*/
|
|
5
|
+
export declare class IppProtocol {
|
|
6
|
+
private printerUrl;
|
|
7
|
+
private printer;
|
|
8
|
+
constructor(address: string, port: number, path?: string);
|
|
9
|
+
/**
|
|
10
|
+
* Get printer attributes/capabilities
|
|
11
|
+
*/
|
|
12
|
+
getAttributes(): Promise<IPrinterCapabilities>;
|
|
13
|
+
/**
|
|
14
|
+
* Print a document
|
|
15
|
+
*/
|
|
16
|
+
print(data: Buffer, options?: IPrintOptions): Promise<IPrintJob>;
|
|
17
|
+
/**
|
|
18
|
+
* Get all jobs
|
|
19
|
+
*/
|
|
20
|
+
getJobs(): Promise<IPrintJob[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Get specific job info
|
|
23
|
+
*/
|
|
24
|
+
getJobInfo(jobId: number): Promise<IPrintJob>;
|
|
25
|
+
/**
|
|
26
|
+
* Cancel a job
|
|
27
|
+
*/
|
|
28
|
+
cancelJob(jobId: number): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Check if printer is available
|
|
31
|
+
*/
|
|
32
|
+
checkAvailability(): Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* Build IPP print message from options
|
|
35
|
+
*/
|
|
36
|
+
private buildPrintMessage;
|
|
37
|
+
/**
|
|
38
|
+
* Parse printer capabilities from attributes
|
|
39
|
+
*/
|
|
40
|
+
private parseCapabilities;
|
|
41
|
+
/**
|
|
42
|
+
* Parse job info from attributes
|
|
43
|
+
*/
|
|
44
|
+
private parseJobInfo;
|
|
45
|
+
}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
/**
|
|
3
|
+
* IPP protocol wrapper using the ipp npm package
|
|
4
|
+
*/
|
|
5
|
+
export class IppProtocol {
|
|
6
|
+
printerUrl;
|
|
7
|
+
printer;
|
|
8
|
+
constructor(address, port, path = '/ipp/print') {
|
|
9
|
+
this.printerUrl = `ipp://${address}:${port}${path}`;
|
|
10
|
+
this.printer = plugins.ipp.Printer(this.printerUrl);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get printer attributes/capabilities
|
|
14
|
+
*/
|
|
15
|
+
async getAttributes() {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
this.printer.execute('Get-Printer-Attributes', null, (err, res) => {
|
|
18
|
+
if (err) {
|
|
19
|
+
reject(err);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const attrs = res['printer-attributes-tag'] || {};
|
|
24
|
+
resolve(this.parseCapabilities(attrs));
|
|
25
|
+
}
|
|
26
|
+
catch (parseErr) {
|
|
27
|
+
reject(parseErr);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Print a document
|
|
34
|
+
*/
|
|
35
|
+
async print(data, options) {
|
|
36
|
+
const msg = this.buildPrintMessage(options);
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
this.printer.execute('Print-Job', { ...msg, data }, (err, res) => {
|
|
39
|
+
if (err) {
|
|
40
|
+
reject(err);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const jobAttrs = res['job-attributes-tag'] || {};
|
|
45
|
+
resolve(this.parseJobInfo(jobAttrs));
|
|
46
|
+
}
|
|
47
|
+
catch (parseErr) {
|
|
48
|
+
reject(parseErr);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get all jobs
|
|
55
|
+
*/
|
|
56
|
+
async getJobs() {
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
this.printer.execute('Get-Jobs', {
|
|
59
|
+
'operation-attributes-tag': {
|
|
60
|
+
'requesting-user-name': 'devicemanager',
|
|
61
|
+
'which-jobs': 'not-completed',
|
|
62
|
+
},
|
|
63
|
+
}, (err, res) => {
|
|
64
|
+
if (err) {
|
|
65
|
+
reject(err);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const jobs = [];
|
|
70
|
+
const jobTags = res['job-attributes-tag'];
|
|
71
|
+
if (Array.isArray(jobTags)) {
|
|
72
|
+
for (const jobAttrs of jobTags) {
|
|
73
|
+
jobs.push(this.parseJobInfo(jobAttrs));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (jobTags && typeof jobTags === 'object') {
|
|
77
|
+
jobs.push(this.parseJobInfo(jobTags));
|
|
78
|
+
}
|
|
79
|
+
resolve(jobs);
|
|
80
|
+
}
|
|
81
|
+
catch (parseErr) {
|
|
82
|
+
reject(parseErr);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get specific job info
|
|
89
|
+
*/
|
|
90
|
+
async getJobInfo(jobId) {
|
|
91
|
+
return new Promise((resolve, reject) => {
|
|
92
|
+
this.printer.execute('Get-Job-Attributes', {
|
|
93
|
+
'operation-attributes-tag': {
|
|
94
|
+
'job-id': jobId,
|
|
95
|
+
},
|
|
96
|
+
}, (err, res) => {
|
|
97
|
+
if (err) {
|
|
98
|
+
reject(err);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const jobAttrs = res['job-attributes-tag'] || {};
|
|
103
|
+
resolve(this.parseJobInfo(jobAttrs));
|
|
104
|
+
}
|
|
105
|
+
catch (parseErr) {
|
|
106
|
+
reject(parseErr);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Cancel a job
|
|
113
|
+
*/
|
|
114
|
+
async cancelJob(jobId) {
|
|
115
|
+
return new Promise((resolve, reject) => {
|
|
116
|
+
this.printer.execute('Cancel-Job', {
|
|
117
|
+
'operation-attributes-tag': {
|
|
118
|
+
'job-id': jobId,
|
|
119
|
+
},
|
|
120
|
+
}, (err, _res) => {
|
|
121
|
+
if (err) {
|
|
122
|
+
reject(err);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
resolve();
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Check if printer is available
|
|
131
|
+
*/
|
|
132
|
+
async checkAvailability() {
|
|
133
|
+
try {
|
|
134
|
+
await this.getAttributes();
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Build IPP print message from options
|
|
143
|
+
*/
|
|
144
|
+
buildPrintMessage(options) {
|
|
145
|
+
const operationAttrs = {
|
|
146
|
+
'requesting-user-name': 'devicemanager',
|
|
147
|
+
'job-name': options?.jobName ?? 'Print Job',
|
|
148
|
+
'document-format': 'application/octet-stream',
|
|
149
|
+
};
|
|
150
|
+
const jobAttrs = {};
|
|
151
|
+
if (options?.copies && options.copies > 1) {
|
|
152
|
+
jobAttrs['copies'] = options.copies;
|
|
153
|
+
}
|
|
154
|
+
if (options?.mediaSize) {
|
|
155
|
+
jobAttrs['media'] = options.mediaSize;
|
|
156
|
+
}
|
|
157
|
+
if (options?.mediaType) {
|
|
158
|
+
jobAttrs['media-type'] = options.mediaType;
|
|
159
|
+
}
|
|
160
|
+
if (options?.sides) {
|
|
161
|
+
jobAttrs['sides'] = options.sides;
|
|
162
|
+
}
|
|
163
|
+
if (options?.quality) {
|
|
164
|
+
const qualityMap = {
|
|
165
|
+
draft: 3,
|
|
166
|
+
normal: 4,
|
|
167
|
+
high: 5,
|
|
168
|
+
};
|
|
169
|
+
jobAttrs['print-quality'] = qualityMap[options.quality] ?? 4;
|
|
170
|
+
}
|
|
171
|
+
if (options?.colorMode) {
|
|
172
|
+
jobAttrs['print-color-mode'] = options.colorMode;
|
|
173
|
+
}
|
|
174
|
+
const msg = {
|
|
175
|
+
'operation-attributes-tag': operationAttrs,
|
|
176
|
+
};
|
|
177
|
+
if (Object.keys(jobAttrs).length > 0) {
|
|
178
|
+
msg['job-attributes-tag'] = jobAttrs;
|
|
179
|
+
}
|
|
180
|
+
return msg;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Parse printer capabilities from attributes
|
|
184
|
+
*/
|
|
185
|
+
parseCapabilities(attrs) {
|
|
186
|
+
const getArray = (key) => {
|
|
187
|
+
const value = attrs[key];
|
|
188
|
+
if (Array.isArray(value))
|
|
189
|
+
return value.map(String);
|
|
190
|
+
if (value !== undefined)
|
|
191
|
+
return [String(value)];
|
|
192
|
+
return [];
|
|
193
|
+
};
|
|
194
|
+
const getNumber = (key, defaultVal) => {
|
|
195
|
+
const value = attrs[key];
|
|
196
|
+
if (typeof value === 'number')
|
|
197
|
+
return value;
|
|
198
|
+
if (typeof value === 'string')
|
|
199
|
+
return parseInt(value) || defaultVal;
|
|
200
|
+
return defaultVal;
|
|
201
|
+
};
|
|
202
|
+
const getBool = (key, defaultVal) => {
|
|
203
|
+
const value = attrs[key];
|
|
204
|
+
if (typeof value === 'boolean')
|
|
205
|
+
return value;
|
|
206
|
+
if (value === 'true' || value === 1)
|
|
207
|
+
return true;
|
|
208
|
+
if (value === 'false' || value === 0)
|
|
209
|
+
return false;
|
|
210
|
+
return defaultVal;
|
|
211
|
+
};
|
|
212
|
+
// Parse resolutions
|
|
213
|
+
const resolutions = [];
|
|
214
|
+
const resSupported = attrs['printer-resolution-supported'];
|
|
215
|
+
if (Array.isArray(resSupported)) {
|
|
216
|
+
for (const res of resSupported) {
|
|
217
|
+
if (typeof res === 'object' && res !== null && 'x' in res) {
|
|
218
|
+
resolutions.push(res.x);
|
|
219
|
+
}
|
|
220
|
+
else if (typeof res === 'number') {
|
|
221
|
+
resolutions.push(res);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (resolutions.length === 0) {
|
|
226
|
+
resolutions.push(300, 600);
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
colorSupported: getBool('color-supported', false),
|
|
230
|
+
duplexSupported: getArray('sides-supported').some((s) => s.includes('two-sided')),
|
|
231
|
+
mediaSizes: getArray('media-supported'),
|
|
232
|
+
mediaTypes: getArray('media-type-supported'),
|
|
233
|
+
resolutions: [...new Set(resolutions)],
|
|
234
|
+
maxCopies: getNumber('copies-supported', 99),
|
|
235
|
+
sidesSupported: getArray('sides-supported'),
|
|
236
|
+
qualitySupported: getArray('print-quality-supported').map(String),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Parse job info from attributes
|
|
241
|
+
*/
|
|
242
|
+
parseJobInfo(attrs) {
|
|
243
|
+
const getString = (key, defaultVal) => {
|
|
244
|
+
const value = attrs[key];
|
|
245
|
+
if (typeof value === 'string')
|
|
246
|
+
return value;
|
|
247
|
+
if (value !== undefined)
|
|
248
|
+
return String(value);
|
|
249
|
+
return defaultVal;
|
|
250
|
+
};
|
|
251
|
+
const getNumber = (key, defaultVal) => {
|
|
252
|
+
const value = attrs[key];
|
|
253
|
+
if (typeof value === 'number')
|
|
254
|
+
return value;
|
|
255
|
+
if (typeof value === 'string')
|
|
256
|
+
return parseInt(value) || defaultVal;
|
|
257
|
+
return defaultVal;
|
|
258
|
+
};
|
|
259
|
+
// Map IPP job state to our state
|
|
260
|
+
const ippState = getNumber('job-state', 3);
|
|
261
|
+
const stateMap = {
|
|
262
|
+
3: 'pending', // pending
|
|
263
|
+
4: 'pending', // pending-held
|
|
264
|
+
5: 'processing', // processing
|
|
265
|
+
6: 'processing', // processing-stopped
|
|
266
|
+
7: 'canceled', // canceled
|
|
267
|
+
8: 'aborted', // aborted
|
|
268
|
+
9: 'completed', // completed
|
|
269
|
+
};
|
|
270
|
+
const createdTime = attrs['time-at-creation'];
|
|
271
|
+
const completedTime = attrs['time-at-completed'];
|
|
272
|
+
return {
|
|
273
|
+
id: getNumber('job-id', 0),
|
|
274
|
+
name: getString('job-name', 'Unknown Job'),
|
|
275
|
+
state: stateMap[ippState] ?? 'pending',
|
|
276
|
+
stateReason: getString('job-state-reasons', undefined),
|
|
277
|
+
createdAt: createdTime ? new Date(createdTime * 1000) : new Date(),
|
|
278
|
+
completedAt: completedTime ? new Date(completedTime * 1000) : undefined,
|
|
279
|
+
pagesPrinted: getNumber('job-media-sheets-completed', undefined),
|
|
280
|
+
pagesTotal: getNumber('job-media-sheets', undefined),
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2wuaXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvcHJvdG9jb2xzL3Byb3RvY29sLmlwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQU96Qzs7R0FFRztBQUNILE1BQU0sT0FBTyxXQUFXO0lBQ2QsVUFBVSxDQUFTO0lBQ25CLE9BQU8sQ0FBeUM7SUFFeEQsWUFBWSxPQUFlLEVBQUUsSUFBWSxFQUFFLE9BQWUsWUFBWTtRQUNwRSxJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsT0FBTyxJQUFJLElBQUksR0FBRyxJQUFJLEVBQUUsQ0FBQztRQUNwRCxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsYUFBYTtRQUN4QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUNsQix3QkFBd0IsRUFDeEIsSUFBSSxFQUNKLENBQUMsR0FBaUIsRUFBRSxHQUE0QixFQUFFLEVBQUU7Z0JBQ2xELElBQUksR0FBRyxFQUFFLENBQUM7b0JBQ1IsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUNaLE9BQU87Z0JBQ1QsQ0FBQztnQkFFRCxJQUFJLENBQUM7b0JBQ0gsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLHdCQUF3QixDQUE0QixJQUFJLEVBQUUsQ0FBQztvQkFDN0UsT0FBTyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUN6QyxDQUFDO2dCQUFDLE9BQU8sUUFBUSxFQUFFLENBQUM7b0JBQ2xCLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDbkIsQ0FBQztZQUNILENBQUMsQ0FDRixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsS0FBSyxDQUFDLElBQVksRUFBRSxPQUF1QjtRQUN0RCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFNUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FDbEIsV0FBVyxFQUNYLEVBQUUsR0FBRyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQ2hCLENBQUMsR0FBaUIsRUFBRSxHQUE0QixFQUFFLEVBQUU7Z0JBQ2xELElBQUksR0FBRyxFQUFFLENBQUM7b0JBQ1IsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUNaLE9BQU87Z0JBQ1QsQ0FBQztnQkFFRCxJQUFJLENBQUM7b0JBQ0gsTUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFDLG9CQUFvQixDQUE0QixJQUFJLEVBQUUsQ0FBQztvQkFDNUUsT0FBTyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztnQkFDdkMsQ0FBQztnQkFBQyxPQUFPLFFBQVEsRUFBRSxDQUFDO29CQUNsQixNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQ25CLENBQUM7WUFDSCxDQUFDLENBQ0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLE9BQU87UUFDbEIsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FDbEIsVUFBVSxFQUNWO2dCQUNFLDBCQUEwQixFQUFFO29CQUMxQixzQkFBc0IsRUFBRSxlQUFlO29CQUN2QyxZQUFZLEVBQUUsZUFBZTtpQkFDOUI7YUFDRixFQUNELENBQUMsR0FBaUIsRUFBRSxHQUE0QixFQUFFLEVBQUU7Z0JBQ2xELElBQUksR0FBRyxFQUFFLENBQUM7b0JBQ1IsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUNaLE9BQU87Z0JBQ1QsQ0FBQztnQkFFRCxJQUFJLENBQUM7b0JBQ0gsTUFBTSxJQUFJLEdBQWdCLEVBQUUsQ0FBQztvQkFDN0IsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLG9CQUFvQixDQUFDLENBQUM7b0JBRTFDLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO3dCQUMzQixLQUFLLE1BQU0sUUFBUSxJQUFJLE9BQU8sRUFBRSxDQUFDOzRCQUMvQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBbUMsQ0FBQyxDQUFDLENBQUM7d0JBQ3BFLENBQUM7b0JBQ0gsQ0FBQzt5QkFBTSxJQUFJLE9BQU8sSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUUsQ0FBQzt3QkFDbEQsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE9BQWtDLENBQUMsQ0FBQyxDQUFDO29CQUNuRSxDQUFDO29CQUVELE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDaEIsQ0FBQztnQkFBQyxPQUFPLFFBQVEsRUFBRSxDQUFDO29CQUNsQixNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQ25CLENBQUM7WUFDSCxDQUFDLENBQ0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLFVBQVUsQ0FBQyxLQUFhO1FBQ25DLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQ2xCLG9CQUFvQixFQUNwQjtnQkFDRSwwQkFBMEIsRUFBRTtvQkFDMUIsUUFBUSxFQUFFLEtBQUs7aUJBQ2hCO2FBQ0YsRUFDRCxDQUFDLEdBQWlCLEVBQUUsR0FBNEIsRUFBRSxFQUFFO2dCQUNsRCxJQUFJLEdBQUcsRUFBRSxDQUFDO29CQUNSLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFDWixPQUFPO2dCQUNULENBQUM7Z0JBRUQsSUFBSSxDQUFDO29CQUNILE1BQU0sUUFBUSxHQUFHLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBNEIsSUFBSSxFQUFFLENBQUM7b0JBQzVFLE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7Z0JBQ3ZDLENBQUM7Z0JBQUMsT0FBTyxRQUFRLEVBQUUsQ0FBQztvQkFDbEIsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUNuQixDQUFDO1lBQ0gsQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxTQUFTLENBQUMsS0FBYTtRQUNsQyxPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUNsQixZQUFZLEVBQ1o7Z0JBQ0UsMEJBQTBCLEVBQUU7b0JBQzFCLFFBQVEsRUFBRSxLQUFLO2lCQUNoQjthQUNGLEVBQ0QsQ0FBQyxHQUFpQixFQUFFLElBQTZCLEVBQUUsRUFBRTtnQkFDbkQsSUFBSSxHQUFHLEVBQUUsQ0FBQztvQkFDUixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQ1osT0FBTztnQkFDVCxDQUFDO2dCQUNELE9BQU8sRUFBRSxDQUFDO1lBQ1osQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxpQkFBaUI7UUFDNUIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDM0IsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ssaUJBQWlCLENBQUMsT0FBdUI7UUFDL0MsTUFBTSxjQUFjLEdBQTRCO1lBQzlDLHNCQUFzQixFQUFFLGVBQWU7WUFDdkMsVUFBVSxFQUFFLE9BQU8sRUFBRSxPQUFPLElBQUksV0FBVztZQUMzQyxpQkFBaUIsRUFBRSwwQkFBMEI7U0FDOUMsQ0FBQztRQUVGLE1BQU0sUUFBUSxHQUE0QixFQUFFLENBQUM7UUFFN0MsSUFBSSxPQUFPLEVBQUUsTUFBTSxJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDMUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFDdEMsQ0FBQztRQUVELElBQUksT0FBTyxFQUFFLFNBQVMsRUFBRSxDQUFDO1lBQ3ZCLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDO1FBQ3hDLENBQUM7UUFFRCxJQUFJLE9BQU8sRUFBRSxTQUFTLEVBQUUsQ0FBQztZQUN2QixRQUFRLENBQUMsWUFBWSxDQUFDLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQztRQUM3QyxDQUFDO1FBRUQsSUFBSSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUM7WUFDbkIsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUM7UUFDcEMsQ0FBQztRQUVELElBQUksT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDO1lBQ3JCLE1BQU0sVUFBVSxHQUEyQjtnQkFDekMsS0FBSyxFQUFFLENBQUM7Z0JBQ1IsTUFBTSxFQUFFLENBQUM7Z0JBQ1QsSUFBSSxFQUFFLENBQUM7YUFDUixDQUFDO1lBQ0YsUUFBUSxDQUFDLGVBQWUsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQy9ELENBQUM7UUFFRCxJQUFJLE9BQU8sRUFBRSxTQUFTLEVBQUUsQ0FBQztZQUN2QixRQUFRLENBQUMsa0JBQWtCLENBQUMsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDO1FBQ25ELENBQUM7UUFFRCxNQUFNLEdBQUcsR0FBNEI7WUFDbkMsMEJBQTBCLEVBQUUsY0FBYztTQUMzQyxDQUFDO1FBRUYsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNyQyxHQUFHLENBQUMsb0JBQW9CLENBQUMsR0FBRyxRQUFRLENBQUM7UUFDdkMsQ0FBQztRQUVELE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUVEOztPQUVHO0lBQ0ssaUJBQWlCLENBQUMsS0FBOEI7UUFDdEQsTUFBTSxRQUFRLEdBQUcsQ0FBQyxHQUFXLEVBQVksRUFBRTtZQUN6QyxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDekIsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztnQkFBRSxPQUFPLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDbkQsSUFBSSxLQUFLLEtBQUssU0FBUztnQkFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDaEQsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDLENBQUM7UUFFRixNQUFNLFNBQVMsR0FBRyxDQUFDLEdBQVcsRUFBRSxVQUFrQixFQUFVLEVBQUU7WUFDNUQsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3pCLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUTtnQkFBRSxPQUFPLEtBQUssQ0FBQztZQUM1QyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVE7Z0JBQUUsT0FBTyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksVUFBVSxDQUFDO1lBQ3BFLE9BQU8sVUFBVSxDQUFDO1FBQ3BCLENBQUMsQ0FBQztRQUVGLE1BQU0sT0FBTyxHQUFHLENBQUMsR0FBVyxFQUFFLFVBQW1CLEVBQVcsRUFBRTtZQUM1RCxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDekIsSUFBSSxPQUFPLEtBQUssS0FBSyxTQUFTO2dCQUFFLE9BQU8sS0FBSyxDQUFDO1lBQzdDLElBQUksS0FBSyxLQUFLLE1BQU0sSUFBSSxLQUFLLEtBQUssQ0FBQztnQkFBRSxPQUFPLElBQUksQ0FBQztZQUNqRCxJQUFJLEtBQUssS0FBSyxPQUFPLElBQUksS0FBSyxLQUFLLENBQUM7Z0JBQUUsT0FBTyxLQUFLLENBQUM7WUFDbkQsT0FBTyxVQUFVLENBQUM7UUFDcEIsQ0FBQyxDQUFDO1FBRUYsb0JBQW9CO1FBQ3BCLE1BQU0sV0FBVyxHQUFhLEVBQUUsQ0FBQztRQUNqQyxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsOEJBQThCLENBQUMsQ0FBQztRQUMzRCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUNoQyxLQUFLLE1BQU0sR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO2dCQUMvQixJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVEsSUFBSSxHQUFHLEtBQUssSUFBSSxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztvQkFDMUQsV0FBVyxDQUFDLElBQUksQ0FBRSxHQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUM3QyxDQUFDO3FCQUFNLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUSxFQUFFLENBQUM7b0JBQ25DLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ3hCLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksV0FBVyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUM3QixXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUM3QixDQUFDO1FBRUQsT0FBTztZQUNMLGNBQWMsRUFBRSxPQUFPLENBQUMsaUJBQWlCLEVBQUUsS0FBSyxDQUFDO1lBQ2pELGVBQWUsRUFDYixRQUFRLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUNyQyxDQUFDLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUN4QjtZQUNILFVBQVUsRUFBRSxRQUFRLENBQUMsaUJBQWlCLENBQUM7WUFDdkMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxzQkFBc0IsQ0FBQztZQUM1QyxXQUFXLEVBQUUsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ3RDLFNBQVMsRUFBRSxTQUFTLENBQUMsa0JBQWtCLEVBQUUsRUFBRSxDQUFDO1lBQzVDLGNBQWMsRUFBRSxRQUFRLENBQUMsaUJBQWlCLENBQUM7WUFDM0MsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLHlCQUF5QixDQUFDLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQztTQUNsRSxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0ssWUFBWSxDQUFDLEtBQThCO1FBQ2pELE1BQU0sU0FBUyxHQUFHLENBQUMsR0FBVyxFQUFFLFVBQWtCLEVBQVUsRUFBRTtZQUM1RCxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDekIsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRO2dCQUFFLE9BQU8sS0FBSyxDQUFDO1lBQzVDLElBQUksS0FBSyxLQUFLLFNBQVM7Z0JBQUUsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDOUMsT0FBTyxVQUFVLENBQUM7UUFDcEIsQ0FBQyxDQUFDO1FBRUYsTUFBTSxTQUFTLEdBQUcsQ0FBQyxHQUFXLEVBQUUsVUFBa0IsRUFBVSxFQUFFO1lBQzVELE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN6QixJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVE7Z0JBQUUsT0FBTyxLQUFLLENBQUM7WUFDNUMsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRO2dCQUFFLE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLFVBQVUsQ0FBQztZQUNwRSxPQUFPLFVBQVUsQ0FBQztRQUNwQixDQUFDLENBQUM7UUFFRixpQ0FBaUM7UUFDakMsTUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMzQyxNQUFNLFFBQVEsR0FBdUM7WUFDbkQsQ0FBQyxFQUFFLFNBQVMsRUFBTSxVQUFVO1lBQzVCLENBQUMsRUFBRSxTQUFTLEVBQU0sZUFBZTtZQUNqQyxDQUFDLEVBQUUsWUFBWSxFQUFHLGFBQWE7WUFDL0IsQ0FBQyxFQUFFLFlBQVksRUFBRyxxQkFBcUI7WUFDdkMsQ0FBQyxFQUFFLFVBQVUsRUFBSyxXQUFXO1lBQzdCLENBQUMsRUFBRSxTQUFTLEVBQU0sVUFBVTtZQUM1QixDQUFDLEVBQUUsV0FBVyxFQUFJLFlBQVk7U0FDL0IsQ0FBQztRQUVGLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzlDLE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBRWpELE9BQU87WUFDTCxFQUFFLEVBQUUsU0FBUyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7WUFDMUIsSUFBSSxFQUFFLFNBQVMsQ0FBQyxVQUFVLEVBQUUsYUFBYSxDQUFDO1lBQzFDLEtBQUssRUFBRSxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksU0FBUztZQUN0QyxXQUFXLEVBQUUsU0FBUyxDQUFDLG1CQUFtQixFQUFFLFNBQVMsQ0FBQztZQUN0RCxTQUFTLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxXQUFxQixHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksRUFBRTtZQUM1RSxXQUFXLEVBQUUsYUFBYSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxhQUF1QixHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTO1lBQ2pGLFlBQVksRUFBRSxTQUFTLENBQUMsNEJBQTRCLEVBQUUsU0FBUyxDQUFDO1lBQ2hFLFVBQVUsRUFBRSxTQUFTLENBQUMsa0JBQWtCLEVBQUUsU0FBUyxDQUFDO1NBQ3JELENBQUM7SUFDSixDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NUT Protocol variable definitions
|
|
3
|
+
*/
|
|
4
|
+
export declare const NUT_VARIABLES: {
|
|
5
|
+
deviceMfr: string;
|
|
6
|
+
deviceModel: string;
|
|
7
|
+
deviceSerial: string;
|
|
8
|
+
deviceType: string;
|
|
9
|
+
upsStatus: string;
|
|
10
|
+
upsAlarm: string;
|
|
11
|
+
upsTime: string;
|
|
12
|
+
upsLoad: string;
|
|
13
|
+
upsTemperature: string;
|
|
14
|
+
batteryCharge: string;
|
|
15
|
+
batteryRuntime: string;
|
|
16
|
+
batteryVoltage: string;
|
|
17
|
+
batteryVoltageNominal: string;
|
|
18
|
+
batteryType: string;
|
|
19
|
+
batteryDate: string;
|
|
20
|
+
batteryTemperature: string;
|
|
21
|
+
inputVoltage: string;
|
|
22
|
+
inputVoltageNominal: string;
|
|
23
|
+
inputFrequency: string;
|
|
24
|
+
inputFrequencyNominal: string;
|
|
25
|
+
inputTransferHigh: string;
|
|
26
|
+
inputTransferLow: string;
|
|
27
|
+
outputVoltage: string;
|
|
28
|
+
outputVoltageNominal: string;
|
|
29
|
+
outputFrequency: string;
|
|
30
|
+
outputCurrent: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* NUT instant commands
|
|
34
|
+
*/
|
|
35
|
+
export declare const NUT_COMMANDS: {
|
|
36
|
+
testBatteryStart: string;
|
|
37
|
+
testBatteryStartQuick: string;
|
|
38
|
+
testBatteryStartDeep: string;
|
|
39
|
+
testBatteryStop: string;
|
|
40
|
+
calibrateStart: string;
|
|
41
|
+
calibrateStop: string;
|
|
42
|
+
shutdown: string;
|
|
43
|
+
shutdownStayOff: string;
|
|
44
|
+
shutdownStop: string;
|
|
45
|
+
shutdownReboot: string;
|
|
46
|
+
beeperEnable: string;
|
|
47
|
+
beeperDisable: string;
|
|
48
|
+
beeperMute: string;
|
|
49
|
+
beeperToggle: string;
|
|
50
|
+
loadOff: string;
|
|
51
|
+
loadOn: string;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* UPS status flags from NUT
|
|
55
|
+
*/
|
|
56
|
+
export type TNutStatusFlag = 'OL' | 'OB' | 'LB' | 'HB' | 'RB' | 'CHRG' | 'DISCHRG' | 'BYPASS' | 'CAL' | 'OFF' | 'OVER' | 'TRIM' | 'BOOST' | 'FSD';
|
|
57
|
+
/**
|
|
58
|
+
* NUT UPS information
|
|
59
|
+
*/
|
|
60
|
+
export interface INutUpsInfo {
|
|
61
|
+
name: string;
|
|
62
|
+
description: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* NUT variable
|
|
66
|
+
*/
|
|
67
|
+
export interface INutVariable {
|
|
68
|
+
name: string;
|
|
69
|
+
value: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* NUT Protocol handler for Network UPS Tools
|
|
73
|
+
* TCP-based text protocol on port 3493
|
|
74
|
+
*/
|
|
75
|
+
export declare class NutProtocol {
|
|
76
|
+
private socket;
|
|
77
|
+
private address;
|
|
78
|
+
private port;
|
|
79
|
+
private connected;
|
|
80
|
+
private responseBuffer;
|
|
81
|
+
private responseResolver;
|
|
82
|
+
private responseRejecter;
|
|
83
|
+
constructor(address: string, port?: number);
|
|
84
|
+
/**
|
|
85
|
+
* Connect to NUT server
|
|
86
|
+
*/
|
|
87
|
+
connect(): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Disconnect from NUT server
|
|
90
|
+
*/
|
|
91
|
+
disconnect(): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Check if connected
|
|
94
|
+
*/
|
|
95
|
+
get isConnected(): boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Handle incoming data
|
|
98
|
+
*/
|
|
99
|
+
private handleData;
|
|
100
|
+
/**
|
|
101
|
+
* Send command and get response
|
|
102
|
+
*/
|
|
103
|
+
private sendCommand;
|
|
104
|
+
/**
|
|
105
|
+
* List available UPS devices
|
|
106
|
+
*/
|
|
107
|
+
listUps(): Promise<INutUpsInfo[]>;
|
|
108
|
+
/**
|
|
109
|
+
* Get all variables for a UPS
|
|
110
|
+
*/
|
|
111
|
+
listVariables(upsName: string): Promise<INutVariable[]>;
|
|
112
|
+
/**
|
|
113
|
+
* Get a specific variable value
|
|
114
|
+
*/
|
|
115
|
+
getVariable(upsName: string, varName: string): Promise<string | null>;
|
|
116
|
+
/**
|
|
117
|
+
* Get multiple variables at once
|
|
118
|
+
*/
|
|
119
|
+
getVariables(upsName: string, varNames: string[]): Promise<Map<string, string>>;
|
|
120
|
+
/**
|
|
121
|
+
* Execute an instant command
|
|
122
|
+
*/
|
|
123
|
+
runCommand(upsName: string, command: string): Promise<boolean>;
|
|
124
|
+
/**
|
|
125
|
+
* List available commands for a UPS
|
|
126
|
+
*/
|
|
127
|
+
listCommands(upsName: string): Promise<string[]>;
|
|
128
|
+
/**
|
|
129
|
+
* Parse UPS status string into flags
|
|
130
|
+
*/
|
|
131
|
+
parseStatus(statusString: string): TNutStatusFlag[];
|
|
132
|
+
/**
|
|
133
|
+
* Get comprehensive UPS status
|
|
134
|
+
*/
|
|
135
|
+
getUpsStatus(upsName: string): Promise<{
|
|
136
|
+
status: TNutStatusFlag[];
|
|
137
|
+
batteryCharge: number;
|
|
138
|
+
batteryRuntime: number;
|
|
139
|
+
inputVoltage: number;
|
|
140
|
+
outputVoltage: number;
|
|
141
|
+
load: number;
|
|
142
|
+
}>;
|
|
143
|
+
/**
|
|
144
|
+
* Get device information
|
|
145
|
+
*/
|
|
146
|
+
getDeviceInfo(upsName: string): Promise<{
|
|
147
|
+
manufacturer: string;
|
|
148
|
+
model: string;
|
|
149
|
+
serial: string;
|
|
150
|
+
type: string;
|
|
151
|
+
}>;
|
|
152
|
+
/**
|
|
153
|
+
* Ensure connected before command
|
|
154
|
+
*/
|
|
155
|
+
private ensureConnected;
|
|
156
|
+
/**
|
|
157
|
+
* Check if a NUT server is reachable
|
|
158
|
+
*/
|
|
159
|
+
static probe(address: string, port?: number, timeout?: number): Promise<boolean>;
|
|
160
|
+
}
|