vrack2-core 0.0.1 → 1.0.0
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/README.md +25 -4
- package/docs/Bootstrap.md +77 -0
- package/docs/Container.md +124 -0
- package/docs/Device.md +272 -0
- package/docs/FastStart.md +111 -0
- package/docs/Structure.md +148 -0
- package/lib/Bootstrap.d.ts +79 -0
- package/lib/Bootstrap.js +103 -0
- package/lib/Container.d.ts +202 -6
- package/lib/Container.js +295 -27
- package/lib/IServiceStructure.d.ts +8 -0
- package/lib/IStructureDevice.d.ts +5 -0
- package/lib/ImportManager.d.ts +85 -3
- package/lib/ImportManager.js +122 -16
- package/lib/MainProcess.d.ts +30 -3
- package/lib/MainProcess.js +28 -6
- package/lib/Utility.d.ts +15 -21
- package/lib/Utility.js +40 -40
- package/lib/actions/Action.d.ts +10 -0
- package/lib/actions/Action.js +10 -0
- package/lib/actions/BasicAction.d.ts +60 -0
- package/lib/actions/BasicAction.js +62 -0
- package/lib/actions/GlobalAction.d.ts +5 -0
- package/lib/actions/GlobalAction.js +5 -0
- package/lib/actions/IAction.d.ts +7 -0
- package/lib/actions/ILocalAction.d.ts +7 -0
- package/lib/boot/BootClass.d.ts +93 -0
- package/lib/boot/BootClass.js +101 -0
- package/lib/boot/DeviceFileStorage.d.ts +38 -0
- package/lib/boot/DeviceFileStorage.js +112 -0
- package/lib/boot/DeviceManager.d.ts +190 -0
- package/lib/boot/DeviceManager.js +306 -0
- package/lib/boot/DeviceMetrics.d.ts +82 -0
- package/lib/boot/DeviceMetrics.js +128 -0
- package/lib/boot/StructureStorage.d.ts +59 -0
- package/lib/boot/StructureStorage.js +125 -0
- package/lib/errors/CoreError.d.ts +42 -25
- package/lib/errors/CoreError.js +44 -24
- package/lib/errors/ErrorManager.d.ts +18 -20
- package/lib/errors/ErrorManager.js +23 -22
- package/lib/index.d.ts +20 -4
- package/lib/index.js +28 -4
- package/lib/metrics/BasicMetric.d.ts +49 -0
- package/lib/metrics/BasicMetric.js +79 -0
- package/lib/metrics/IMetricSettings.d.ts +32 -0
- package/lib/metrics/IMetricSettings.js +2 -0
- package/lib/metrics/IvMs.d.ts +9 -0
- package/lib/metrics/IvMs.js +22 -0
- package/lib/metrics/IvS.d.ts +9 -0
- package/lib/metrics/IvS.js +22 -0
- package/lib/metrics/IvUs.d.ts +9 -0
- package/lib/metrics/IvUs.js +22 -0
- package/lib/metrics/Metric.d.ts +17 -0
- package/lib/metrics/Metric.js +27 -0
- package/lib/ports/BasicPort.d.ts +39 -0
- package/lib/ports/BasicPort.js +39 -0
- package/lib/ports/ILocalPort.d.ts +7 -0
- package/lib/ports/IPort.d.ts +7 -0
- package/lib/ports/Port.d.ts +10 -0
- package/lib/ports/Port.js +10 -0
- package/lib/ports/ReturnPort.d.ts +5 -0
- package/lib/ports/ReturnPort.js +5 -0
- package/lib/service/Device.d.ts +213 -78
- package/lib/service/Device.js +185 -83
- package/lib/service/DeviceConnect.d.ts +4 -8
- package/lib/service/DeviceConnect.js +4 -8
- package/lib/service/DevicePort.d.ts +15 -6
- package/lib/service/DevicePort.js +29 -12
- package/lib/service/IDeviceEvent.d.ts +4 -1
- package/lib/validator/IValidationProblem.d.ts +7 -0
- package/lib/validator/IValidationRule.d.ts +12 -0
- package/lib/validator/IValidationSubrule.d.ts +2 -0
- package/lib/validator/Rule.d.ts +6 -2
- package/lib/validator/Rule.js +12 -2
- package/lib/validator/Validator.d.ts +48 -3
- package/lib/validator/Validator.js +70 -18
- package/lib/validator/types/AnyType.d.ts +17 -0
- package/lib/validator/types/AnyType.js +34 -0
- package/lib/validator/types/ArrayType.d.ts +37 -4
- package/lib/validator/types/ArrayType.js +42 -6
- package/lib/validator/types/BasicType.d.ts +67 -7
- package/lib/validator/types/BasicType.js +74 -8
- package/lib/validator/types/BooleanType.d.ts +23 -0
- package/lib/validator/types/BooleanType.js +47 -0
- package/lib/validator/types/FunctionType.d.ts +17 -0
- package/lib/validator/types/FunctionType.js +38 -0
- package/lib/validator/types/NumberType.d.ts +40 -5
- package/lib/validator/types/NumberType.js +53 -14
- package/lib/validator/types/ObjectType.d.ts +32 -5
- package/lib/validator/types/ObjectType.js +42 -8
- package/lib/validator/types/StringType.d.ts +30 -5
- package/lib/validator/types/StringType.js +33 -7
- package/package.json +10 -9
- package/src/Bootstrap.ts +122 -0
- package/src/Container.ts +411 -43
- package/src/IServiceStructure.ts +9 -0
- package/src/IStructureDevice.ts +5 -0
- package/src/ImportManager.ts +119 -11
- package/src/MainProcess.ts +53 -8
- package/src/Utility.ts +35 -36
- package/src/actions/Action.ts +12 -0
- package/src/actions/BasicAction.ts +63 -0
- package/src/actions/GlobalAction.ts +5 -0
- package/src/actions/IAction.ts +7 -0
- package/src/actions/ILocalAction.ts +7 -0
- package/src/boot/BootClass.ts +117 -0
- package/src/boot/DeviceFileStorage.ts +96 -0
- package/src/boot/DeviceManager.ts +339 -0
- package/src/boot/DeviceMetrics.ts +129 -0
- package/src/boot/StructureStorage.ts +108 -0
- package/src/errors/CoreError.ts +52 -26
- package/src/errors/ErrorManager.ts +46 -33
- package/src/index.ts +30 -6
- package/src/metrics/BasicMetric.ts +84 -0
- package/src/metrics/IMetricSettings.ts +38 -0
- package/src/metrics/IvMs.ts +18 -0
- package/src/metrics/IvS.ts +18 -0
- package/src/metrics/IvUs.ts +17 -0
- package/src/metrics/Metric.ts +25 -0
- package/src/ports/BasicPort.ts +39 -0
- package/src/ports/ILocalPort.ts +7 -0
- package/src/ports/IPort.ts +7 -0
- package/src/ports/Port.ts +11 -1
- package/src/ports/ReturnPort.ts +5 -0
- package/src/service/Device.ts +234 -103
- package/src/service/DeviceConnect.ts +4 -8
- package/src/service/DevicePort.ts +30 -11
- package/src/service/IDeviceEvent.ts +4 -1
- package/src/validator/IValidationProblem.ts +7 -0
- package/src/validator/IValidationRule.ts +12 -0
- package/src/validator/IValidationSubrule.ts +3 -0
- package/src/validator/Rule.ts +16 -2
- package/src/validator/Validator.ts +74 -23
- package/src/validator/types/AnyType.ts +32 -0
- package/src/validator/types/ArrayType.ts +43 -7
- package/src/validator/types/BasicType.ts +78 -9
- package/src/validator/types/BooleanType.ts +49 -0
- package/src/validator/types/FunctionType.ts +39 -0
- package/src/validator/types/NumberType.ts +53 -15
- package/src/validator/types/ObjectType.ts +52 -14
- package/src/validator/types/StringType.ts +34 -10
- package/docs/RU-README.md +0 -6
- package/lib/DeviceManager.d.ts +0 -32
- package/lib/DeviceManager.js +0 -143
- package/lib/test.d.ts +0 -1
- package/lib/test.js +0 -58
- package/src/DeviceManager.ts +0 -124
- package/src/test.ts +0 -82
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
const path_1 = __importDefault(require("path"));
|
|
39
|
+
const fs_1 = __importDefault(require("fs"));
|
|
40
|
+
const ErrorManager_1 = __importDefault(require("../errors/ErrorManager"));
|
|
41
|
+
const Rule_1 = __importDefault(require("../validator/Rule"));
|
|
42
|
+
const CoreError_1 = __importDefault(require("../errors/CoreError"));
|
|
43
|
+
const BootClass_1 = __importDefault(require("./BootClass"));
|
|
44
|
+
const ImportManager_1 = __importDefault(require("../ImportManager"));
|
|
45
|
+
ErrorManager_1.default.register('DeviceManager', 'S5dBTBKTnVbF', 'DM_DEVICE_NOT_FOUND', 'Device not found', {
|
|
46
|
+
device: Rule_1.default.string().require().example('Master').description('Device name')
|
|
47
|
+
});
|
|
48
|
+
ErrorManager_1.default.register('DeviceManager', '2CJSDE95V9O1', 'DM_LIST_NOT_FOUND', 'list.json not found', {
|
|
49
|
+
vendor: Rule_1.default.string().require().example('vrack').description('Device group name')
|
|
50
|
+
});
|
|
51
|
+
ErrorManager_1.default.register('DeviceManager', 'BPX96F93ZCJA', 'DM_LIST_INCORRECT', 'list.json is not correct', {
|
|
52
|
+
vendor: Rule_1.default.string().require().example('vrack').description('Device group name')
|
|
53
|
+
});
|
|
54
|
+
ErrorManager_1.default.register('DeviceManager', 'H1NDNVCOLWST', 'DM_VENDOR_NOT_FOUND', 'Vendor not found', {
|
|
55
|
+
vendor: Rule_1.default.string().require().example('vrack').description('Vendor name')
|
|
56
|
+
});
|
|
57
|
+
ErrorManager_1.default.register('DeviceManager', 'HQ62LW1YLTDE', 'DM_GET_INFO_EXCEPTION', 'Error retrieving device data, see error in attachment', {});
|
|
58
|
+
/**
|
|
59
|
+
* BootClass which generates a list of available devices for the container.
|
|
60
|
+
* Provides the ability to initialize devices and provide information about them
|
|
61
|
+
*
|
|
62
|
+
*
|
|
63
|
+
* @see get
|
|
64
|
+
*/
|
|
65
|
+
class DeviceManager extends BootClass_1.default {
|
|
66
|
+
constructor() {
|
|
67
|
+
super(...arguments);
|
|
68
|
+
/**
|
|
69
|
+
* Contains a list of devices and their full path to the class
|
|
70
|
+
* Like a:
|
|
71
|
+
*
|
|
72
|
+
* ```js
|
|
73
|
+
* {
|
|
74
|
+
* "vendorname.Devicename": '/path/to/js/file.js'
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
* */
|
|
78
|
+
this.devices = new Map();
|
|
79
|
+
/**
|
|
80
|
+
* Vendor array.
|
|
81
|
+
*
|
|
82
|
+
* @see IDeviceVendor
|
|
83
|
+
*/
|
|
84
|
+
this.vendorList = [];
|
|
85
|
+
}
|
|
86
|
+
checkOptions() {
|
|
87
|
+
return {
|
|
88
|
+
dir: Rule_1.default.string().require().default('./devices'),
|
|
89
|
+
systemDir: Rule_1.default.string().require().default(ImportManager_1.default.systemPath()),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
process() {
|
|
93
|
+
this.updateDeviceList();
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Return vendor list
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* ['vrack', 'basic', 'net']
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
getVendorList() {
|
|
104
|
+
const result = [];
|
|
105
|
+
for (const dgroup of this.vendorList)
|
|
106
|
+
result.push(dgroup.name);
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Returns a list of devices from a specific vendor
|
|
111
|
+
*
|
|
112
|
+
* @param vendor Vendor name
|
|
113
|
+
* @see getVendorList()
|
|
114
|
+
*/
|
|
115
|
+
getVendorDeviceList(vendor) {
|
|
116
|
+
const vgroup = this.findVendor(vendor);
|
|
117
|
+
if (typeof vgroup === "boolean")
|
|
118
|
+
throw ErrorManager_1.default.make('DM_VENDOR_NOT_FOUND', { vendor }).setTrace(new Error());
|
|
119
|
+
return vgroup.deviceList;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Exports all basic device parameters and collects them in one object
|
|
123
|
+
* Used to generate documentation for the device
|
|
124
|
+
*
|
|
125
|
+
* @see IDeivceInfo
|
|
126
|
+
*/
|
|
127
|
+
getDeviceInfo(vendor, device) {
|
|
128
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
129
|
+
const di = [vendor, device].join('.');
|
|
130
|
+
const DeviceClass = yield this.get(di);
|
|
131
|
+
const dev = new DeviceClass('1', di, this);
|
|
132
|
+
const result = { actions: {}, metrics: {}, inputs: {}, outputs: {}, options: {}, description: '' };
|
|
133
|
+
try {
|
|
134
|
+
const preOptions = dev.checkOptions();
|
|
135
|
+
for (const oName in preOptions)
|
|
136
|
+
result.options[oName] = preOptions[oName].export();
|
|
137
|
+
const dInputs = dev.inputs();
|
|
138
|
+
for (const iName in dInputs)
|
|
139
|
+
result.inputs[iName] = dInputs[iName].export();
|
|
140
|
+
const dOutputs = dev.outputs();
|
|
141
|
+
for (const oName in dOutputs)
|
|
142
|
+
result.outputs[oName] = dOutputs[oName].export();
|
|
143
|
+
const dActions = dev.actions();
|
|
144
|
+
for (const aName in dActions)
|
|
145
|
+
result.actions[aName] = dActions[aName].export();
|
|
146
|
+
const dMetrics = dev.metrics();
|
|
147
|
+
for (const mName in dMetrics)
|
|
148
|
+
result.metrics[mName] = dMetrics[mName].export();
|
|
149
|
+
result.description = dev.description();
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
throw ErrorManager_1.default.make('DM_GET_INFO_EXCEPTION').setTrace(new Error).add(error);
|
|
153
|
+
}
|
|
154
|
+
return result;
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Method for updating the device list
|
|
159
|
+
* Updates the available device lists.
|
|
160
|
+
*
|
|
161
|
+
* Searches the directory specified in `options.dir` and adds all directories in it as vendors.
|
|
162
|
+
* Each folder attempts to read the list.json file to get a list of vendor devices
|
|
163
|
+
*
|
|
164
|
+
* Two types of list.json file definition are supported
|
|
165
|
+
*
|
|
166
|
+
* First type - array:
|
|
167
|
+
*
|
|
168
|
+
* ```json
|
|
169
|
+
* ['Device1', 'Device2', 'Device3']
|
|
170
|
+
* ```
|
|
171
|
+
* Second type - Object
|
|
172
|
+
* This approach allows you to point to devices that are deeper than the vendor's root folder
|
|
173
|
+
*
|
|
174
|
+
* ```json
|
|
175
|
+
* {
|
|
176
|
+
* "Master": "devices/Master",
|
|
177
|
+
* "Interval": "devices/Interval",
|
|
178
|
+
* "Guard": "devices/Guard",
|
|
179
|
+
* }
|
|
180
|
+
* ```
|
|
181
|
+
*
|
|
182
|
+
* @see arrayDeviceListPrepare()
|
|
183
|
+
* @see objectDeviceListPrepare()
|
|
184
|
+
*/
|
|
185
|
+
updateDeviceList() {
|
|
186
|
+
this.vendorList = [];
|
|
187
|
+
this.devices.clear();
|
|
188
|
+
const dirs = ImportManager_1.default.dirList(path_1.default.join(this.options.systemDir, this.options.dir)).sort();
|
|
189
|
+
for (const vendor of dirs) {
|
|
190
|
+
const group = {
|
|
191
|
+
name: vendor,
|
|
192
|
+
dir: this.options.dir,
|
|
193
|
+
deviceList: [],
|
|
194
|
+
errors: [],
|
|
195
|
+
description: ''
|
|
196
|
+
};
|
|
197
|
+
this.vendorList.push(group);
|
|
198
|
+
const listPath = path_1.default.join(this.options.systemDir, this.options.dir, vendor, 'list.json');
|
|
199
|
+
if (!fs_1.default.existsSync(listPath)) {
|
|
200
|
+
group.errors.push(ErrorManager_1.default.make('DM_LIST_NOT_FOUND', { vendor }).setTrace(new Error));
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
const list = JSON.parse(fs_1.default.readFileSync(listPath).toString('utf-8'));
|
|
205
|
+
if (Array.isArray(list)) { // if device list like a [ 'DeviceName', 'DeviceTwo' ]
|
|
206
|
+
group.deviceList = this.arrayDeviceListPrepare(list, group);
|
|
207
|
+
}
|
|
208
|
+
else if (typeof list === "object") { // if device list lie a { DeviceID?: 'PathToDevice' }
|
|
209
|
+
group.deviceList = this.objectDeviceListPrepare(list, group);
|
|
210
|
+
}
|
|
211
|
+
else
|
|
212
|
+
throw new Error();
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
if (err instanceof CoreError_1.default)
|
|
216
|
+
group.errors.push(err);
|
|
217
|
+
else
|
|
218
|
+
group.errors.push(ErrorManager_1.default.make('DM_LIST_INCORRECT', { vendor }).setTrace(new Error));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Return class of device
|
|
224
|
+
*
|
|
225
|
+
* Requires special device string of path
|
|
226
|
+
* example "vrack.System" where "vrack" is vendor and "System" is device class
|
|
227
|
+
* @param {string} device Device path string
|
|
228
|
+
*/
|
|
229
|
+
get(device, updateList = true) {
|
|
230
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
231
|
+
const p = this.devices.get(device); // return device path or undefined
|
|
232
|
+
if (typeof p === 'string') {
|
|
233
|
+
const deviceClass = yield Promise.resolve(`${p}`).then(s => __importStar(require(s))); // try import
|
|
234
|
+
if (deviceClass.default)
|
|
235
|
+
return deviceClass.default;
|
|
236
|
+
}
|
|
237
|
+
// Устройство не найдено, но не исключено что если перестроить дерево
|
|
238
|
+
// вендоров и устройств все будет так же
|
|
239
|
+
// По умолчанию мы попытаемся обновить дерево
|
|
240
|
+
if (updateList) {
|
|
241
|
+
yield this.updateDeviceList();
|
|
242
|
+
return yield this.get(device, false);
|
|
243
|
+
}
|
|
244
|
+
throw ErrorManager_1.default.make('DM_DEVICE_NOT_FOUND', { device });
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Find vendor by name
|
|
249
|
+
*
|
|
250
|
+
* Not found if return boolean
|
|
251
|
+
*/
|
|
252
|
+
findVendor(vendor) {
|
|
253
|
+
for (const dgroup of this.vendorList)
|
|
254
|
+
if (dgroup.name === vendor)
|
|
255
|
+
return dgroup;
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Processes a list of devices as an Array
|
|
260
|
+
*
|
|
261
|
+
* Takes an Array of type
|
|
262
|
+
* ```
|
|
263
|
+
* ['DeviceName', 'DeviceName2']
|
|
264
|
+
* ```
|
|
265
|
+
* @return {Array<string>} Sorted list
|
|
266
|
+
*/
|
|
267
|
+
arrayDeviceListPrepare(list, group) {
|
|
268
|
+
for (const name of list) {
|
|
269
|
+
const reqPath = path_1.default.join(this.options.systemDir, this.options.dir, group.name, name);
|
|
270
|
+
if (!fs_1.default.existsSync(reqPath + '.js')) {
|
|
271
|
+
group.errors.push(ErrorManager_1.default.make('DM_DEVICE_NOT_FOUND', { device: name }));
|
|
272
|
+
}
|
|
273
|
+
this.devices.set(group.name + '.' + name, reqPath);
|
|
274
|
+
}
|
|
275
|
+
list.sort();
|
|
276
|
+
return list;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Processes a list of devices as an object
|
|
280
|
+
*
|
|
281
|
+
* Takes an object of type
|
|
282
|
+
* ```
|
|
283
|
+
* {
|
|
284
|
+
* DeviceName: 'path/to/Device'
|
|
285
|
+
* }
|
|
286
|
+
* ```
|
|
287
|
+
*
|
|
288
|
+
* return keys of list
|
|
289
|
+
* ```
|
|
290
|
+
* ['DeviceName']
|
|
291
|
+
* ```
|
|
292
|
+
*
|
|
293
|
+
* Set in this.devices for device name requiere path
|
|
294
|
+
*/
|
|
295
|
+
objectDeviceListPrepare(list, group) {
|
|
296
|
+
for (const name in list) {
|
|
297
|
+
const reqPath = path_1.default.join(this.options.systemDir, this.options.dir, group.name, list[name]);
|
|
298
|
+
if (!fs_1.default.existsSync(reqPath + '.js')) {
|
|
299
|
+
group.errors.push(ErrorManager_1.default.make('DM_DEVICE_NOT_FOUND', { device: name }).setTrace(new Error));
|
|
300
|
+
}
|
|
301
|
+
this.devices.set(group.name + '.' + name, reqPath);
|
|
302
|
+
}
|
|
303
|
+
return Object.keys(list).sort();
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
exports.default = DeviceManager;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Interval, SingleDB } from "vrack-db";
|
|
2
|
+
import IDeviceEvent from "../service/IDeviceEvent";
|
|
3
|
+
import BootClass from "./BootClass";
|
|
4
|
+
import IMetricSettings from "../metrics/IMetricSettings";
|
|
5
|
+
/**
|
|
6
|
+
* A class to support metrics inside devices
|
|
7
|
+
* Using a database vrack-db. Collects and stores container metrics
|
|
8
|
+
*
|
|
9
|
+
* @see SingleDB
|
|
10
|
+
*
|
|
11
|
+
* Uses the `device.metric` and `device.register.metric` events
|
|
12
|
+
*
|
|
13
|
+
* @see deviceMetric()
|
|
14
|
+
* @see deviceRegiterMetric()
|
|
15
|
+
*/
|
|
16
|
+
export default class DeviceMetrics extends BootClass {
|
|
17
|
+
/**
|
|
18
|
+
* VRack-DB class instance
|
|
19
|
+
*/
|
|
20
|
+
DB: SingleDB;
|
|
21
|
+
process(): void;
|
|
22
|
+
/**
|
|
23
|
+
* Checks if the metric exists in the device
|
|
24
|
+
*
|
|
25
|
+
* @param device Device ID
|
|
26
|
+
* @param name Registered metric name
|
|
27
|
+
*/
|
|
28
|
+
has(device: string, name: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Read device metric from the database
|
|
31
|
+
*
|
|
32
|
+
* @param device Device ID
|
|
33
|
+
* @param name Registered metric name
|
|
34
|
+
* @param period Period in the format 'now-6h:now' @see SingleDB.read
|
|
35
|
+
* @param precision Accuracy interval '15m', '5s', '1h' or count of metrics 10, 200, 1500
|
|
36
|
+
* @param precision func Data aggregation function @see SingleDB.read
|
|
37
|
+
*/
|
|
38
|
+
read(device: string, name: string, period: string, precision: string | number, func?: string): import("vrack-db").IMetricReadResult;
|
|
39
|
+
/**
|
|
40
|
+
* Registers the device metric
|
|
41
|
+
*
|
|
42
|
+
* When a device is initialized - the container gets a list of
|
|
43
|
+
* device metrics and passes them to the `device.register.metric` event for each metric.
|
|
44
|
+
*
|
|
45
|
+
* @param nEvent Object like a { device: 'Device ID', data: 'metric.name', trace: IMetricSettings object}
|
|
46
|
+
* @see IMetricSettings
|
|
47
|
+
* @see registerMetric
|
|
48
|
+
*/
|
|
49
|
+
protected deviceRegiterMetric(nEvent: IDeviceEvent): void;
|
|
50
|
+
/**
|
|
51
|
+
* @see deviceRegiterMetric
|
|
52
|
+
* */
|
|
53
|
+
protected registerMetric(path: string, metric: IMetricSettings): void;
|
|
54
|
+
/**
|
|
55
|
+
* A method of writing a metric to a database.
|
|
56
|
+
*
|
|
57
|
+
* @param nEvent Object like a { device: 'Device ID', data: 'metric.name', trace: { value: metric value 123, modify: function of vrack db modify } }
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* deviceMetric({
|
|
61
|
+
* device: 'Device ID',
|
|
62
|
+
* data: 'metric.name',
|
|
63
|
+
* trace: { value: 5.25, modify: 'last'}
|
|
64
|
+
* })
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
protected deviceMetric(nEvent: IDeviceEvent): void;
|
|
68
|
+
/**
|
|
69
|
+
* Selects the interval class depending on the specified minimal time unit
|
|
70
|
+
*
|
|
71
|
+
* @param interval s | ms | us
|
|
72
|
+
*
|
|
73
|
+
*/
|
|
74
|
+
protected selectInterval(interval: string): typeof Interval;
|
|
75
|
+
/**
|
|
76
|
+
* Return metric path
|
|
77
|
+
*
|
|
78
|
+
* @param device Device ID
|
|
79
|
+
* @param name Metric name
|
|
80
|
+
*/
|
|
81
|
+
protected getMetricPath(device: string, name: string): string;
|
|
82
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright © 2025 Boris Bobylev. All rights reserved.
|
|
4
|
+
* Licensed under the Apache License, Version 2.0
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
const vrack_db_1 = require("vrack-db");
|
|
11
|
+
const BootClass_1 = __importDefault(require("./BootClass"));
|
|
12
|
+
/**
|
|
13
|
+
* A class to support metrics inside devices
|
|
14
|
+
* Using a database vrack-db. Collects and stores container metrics
|
|
15
|
+
*
|
|
16
|
+
* @see SingleDB
|
|
17
|
+
*
|
|
18
|
+
* Uses the `device.metric` and `device.register.metric` events
|
|
19
|
+
*
|
|
20
|
+
* @see deviceMetric()
|
|
21
|
+
* @see deviceRegiterMetric()
|
|
22
|
+
*/
|
|
23
|
+
class DeviceMetrics extends BootClass_1.default {
|
|
24
|
+
constructor() {
|
|
25
|
+
super(...arguments);
|
|
26
|
+
/**
|
|
27
|
+
* VRack-DB class instance
|
|
28
|
+
*/
|
|
29
|
+
this.DB = new vrack_db_1.SingleDB();
|
|
30
|
+
}
|
|
31
|
+
process() {
|
|
32
|
+
this.Container.on('device.metric', this.deviceMetric.bind(this));
|
|
33
|
+
this.Container.on('device.register.metric', this.deviceRegiterMetric.bind(this));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Checks if the metric exists in the device
|
|
37
|
+
*
|
|
38
|
+
* @param device Device ID
|
|
39
|
+
* @param name Registered metric name
|
|
40
|
+
*/
|
|
41
|
+
has(device, name) {
|
|
42
|
+
const path = this.getMetricPath(device, name);
|
|
43
|
+
if (!this.DB.has(path))
|
|
44
|
+
return false;
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Read device metric from the database
|
|
49
|
+
*
|
|
50
|
+
* @param device Device ID
|
|
51
|
+
* @param name Registered metric name
|
|
52
|
+
* @param period Period in the format 'now-6h:now' @see SingleDB.read
|
|
53
|
+
* @param precision Accuracy interval '15m', '5s', '1h' or count of metrics 10, 200, 1500
|
|
54
|
+
* @param precision func Data aggregation function @see SingleDB.read
|
|
55
|
+
*/
|
|
56
|
+
read(device, name, period, precision, func) {
|
|
57
|
+
const path = this.getMetricPath(device, name);
|
|
58
|
+
return this.DB.read(path, period, precision, func);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Registers the device metric
|
|
62
|
+
*
|
|
63
|
+
* When a device is initialized - the container gets a list of
|
|
64
|
+
* device metrics and passes them to the `device.register.metric` event for each metric.
|
|
65
|
+
*
|
|
66
|
+
* @param nEvent Object like a { device: 'Device ID', data: 'metric.name', trace: IMetricSettings object}
|
|
67
|
+
* @see IMetricSettings
|
|
68
|
+
* @see registerMetric
|
|
69
|
+
*/
|
|
70
|
+
deviceRegiterMetric(nEvent) {
|
|
71
|
+
this.registerMetric(this.getMetricPath(nEvent.device, nEvent.data), nEvent.trace);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* @see deviceRegiterMetric
|
|
75
|
+
* */
|
|
76
|
+
registerMetric(path, metric) {
|
|
77
|
+
this.DB.metric({
|
|
78
|
+
name: path,
|
|
79
|
+
retentions: metric.retentions,
|
|
80
|
+
tStorage: metric.tType,
|
|
81
|
+
vStorage: metric.vType,
|
|
82
|
+
CInterval: this.selectInterval(metric.interval)
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* A method of writing a metric to a database.
|
|
87
|
+
*
|
|
88
|
+
* @param nEvent Object like a { device: 'Device ID', data: 'metric.name', trace: { value: metric value 123, modify: function of vrack db modify } }
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* deviceMetric({
|
|
92
|
+
* device: 'Device ID',
|
|
93
|
+
* data: 'metric.name',
|
|
94
|
+
* trace: { value: 5.25, modify: 'last'}
|
|
95
|
+
* })
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
deviceMetric(nEvent) {
|
|
99
|
+
const path = this.getMetricPath(nEvent.device, nEvent.data);
|
|
100
|
+
if (!this.DB.has(path))
|
|
101
|
+
return;
|
|
102
|
+
this.DB.write(path, nEvent.trace.value, 0, nEvent.trace.modify);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Selects the interval class depending on the specified minimal time unit
|
|
106
|
+
*
|
|
107
|
+
* @param interval s | ms | us
|
|
108
|
+
*
|
|
109
|
+
*/
|
|
110
|
+
selectInterval(interval) {
|
|
111
|
+
switch (interval) {
|
|
112
|
+
case 's': return vrack_db_1.Interval;
|
|
113
|
+
case 'ms': return vrack_db_1.IntervalMs;
|
|
114
|
+
case 'us': return vrack_db_1.IntervalUs;
|
|
115
|
+
}
|
|
116
|
+
return vrack_db_1.Interval;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Return metric path
|
|
120
|
+
*
|
|
121
|
+
* @param device Device ID
|
|
122
|
+
* @param name Metric name
|
|
123
|
+
*/
|
|
124
|
+
getMetricPath(device, name) {
|
|
125
|
+
return (device + '.' + name).toLowerCase();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
exports.default = DeviceMetrics;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import BootClass from "./BootClass";
|
|
2
|
+
import BasicType from "../validator/types/BasicType";
|
|
3
|
+
import { IContainerStructure } from "../Container";
|
|
4
|
+
/**
|
|
5
|
+
* A boot class for storing the structure of a container.
|
|
6
|
+
*
|
|
7
|
+
* When a container is created, it is assigned a unique identifier.
|
|
8
|
+
* This identifier is used as parameters of methods.
|
|
9
|
+
*
|
|
10
|
+
* @see getById
|
|
11
|
+
* @see updateById
|
|
12
|
+
*
|
|
13
|
+
* When the container is loaded it calls “beforeLoaded”.
|
|
14
|
+
* At this point it updates the structure from disk to the structure
|
|
15
|
+
* of the container itself and writes the changes
|
|
16
|
+
*
|
|
17
|
+
* @see beforeLoadedUpdate
|
|
18
|
+
*
|
|
19
|
+
* */
|
|
20
|
+
export default class StructureStorage extends BootClass {
|
|
21
|
+
checkOptions(): {
|
|
22
|
+
[key: string]: BasicType;
|
|
23
|
+
};
|
|
24
|
+
process(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Updates the structure on disk using the structure of
|
|
27
|
+
* the container itself when it is loaded
|
|
28
|
+
*
|
|
29
|
+
*
|
|
30
|
+
* @see StructureStorage.process
|
|
31
|
+
*/
|
|
32
|
+
beforeLoadedUpdate(): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Returns structure by container identifier
|
|
35
|
+
*
|
|
36
|
+
* @param id Container ID
|
|
37
|
+
*/
|
|
38
|
+
getById(id: string): Promise<IContainerStructure>;
|
|
39
|
+
/**
|
|
40
|
+
* Updating the container structure
|
|
41
|
+
*
|
|
42
|
+
* @param id Container ID
|
|
43
|
+
* @param structure updated container structure object
|
|
44
|
+
*/
|
|
45
|
+
updateById(id: string, structure: IContainerStructure): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Updates the display structure parameter from the file structure
|
|
48
|
+
*
|
|
49
|
+
* @param cStruct now container structure
|
|
50
|
+
* @param structure new structure
|
|
51
|
+
*/
|
|
52
|
+
protected updateStructure(cStruct: IContainerStructure, structure: IContainerStructure, id: string): void;
|
|
53
|
+
/**
|
|
54
|
+
* Forms the path to the structure file by its identifier
|
|
55
|
+
*
|
|
56
|
+
* @param id Container ID
|
|
57
|
+
*/
|
|
58
|
+
protected makeFilePath(id: string): string;
|
|
59
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright © 2024 Boris Bobylev. All rights reserved.
|
|
4
|
+
* Licensed under the Apache License, Version 2.0
|
|
5
|
+
*/
|
|
6
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
7
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
8
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
9
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
10
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
11
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
12
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
16
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
const BootClass_1 = __importDefault(require("./BootClass"));
|
|
20
|
+
const Rule_1 = __importDefault(require("../validator/Rule"));
|
|
21
|
+
const fs_1 = require("fs");
|
|
22
|
+
const path_1 = __importDefault(require("path"));
|
|
23
|
+
const ImportManager_1 = __importDefault(require("../ImportManager"));
|
|
24
|
+
const ErrorManager_1 = __importDefault(require("../errors/ErrorManager"));
|
|
25
|
+
ErrorManager_1.default.register('StructureStorage', 'FKb5raEUDFgU', 'SS_STRUCT_NOT_FOUND', 'Structure ID not found', {
|
|
26
|
+
id: Rule_1.default.string().require().example('vrack').description('Structure id')
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* A boot class for storing the structure of a container.
|
|
30
|
+
*
|
|
31
|
+
* When a container is created, it is assigned a unique identifier.
|
|
32
|
+
* This identifier is used as parameters of methods.
|
|
33
|
+
*
|
|
34
|
+
* @see getById
|
|
35
|
+
* @see updateById
|
|
36
|
+
*
|
|
37
|
+
* When the container is loaded it calls “beforeLoaded”.
|
|
38
|
+
* At this point it updates the structure from disk to the structure
|
|
39
|
+
* of the container itself and writes the changes
|
|
40
|
+
*
|
|
41
|
+
* @see beforeLoadedUpdate
|
|
42
|
+
*
|
|
43
|
+
* */
|
|
44
|
+
class StructureStorage extends BootClass_1.default {
|
|
45
|
+
checkOptions() {
|
|
46
|
+
return {
|
|
47
|
+
structureDir: Rule_1.default.string().require().default('./structure')
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
process() {
|
|
51
|
+
if (!(0, fs_1.existsSync)(this.options.structureDir))
|
|
52
|
+
(0, fs_1.mkdirSync)(this.options.structureDir, { recursive: true });
|
|
53
|
+
this.Container.on('beforeLoaded', this.beforeLoadedUpdate.bind(this));
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Updates the structure on disk using the structure of
|
|
57
|
+
* the container itself when it is loaded
|
|
58
|
+
*
|
|
59
|
+
*
|
|
60
|
+
* @see StructureStorage.process
|
|
61
|
+
*/
|
|
62
|
+
beforeLoadedUpdate() {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
const fp = this.makeFilePath(this.Container.id);
|
|
65
|
+
let structure = {};
|
|
66
|
+
try {
|
|
67
|
+
if ((0, fs_1.existsSync)(fp))
|
|
68
|
+
structure = ImportManager_1.default.importJSON(fp);
|
|
69
|
+
const cStruct = yield this.Container.getStructure();
|
|
70
|
+
this.updateStructure(cStruct, structure, this.Container.id);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
this.error(error);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Returns structure by container identifier
|
|
79
|
+
*
|
|
80
|
+
* @param id Container ID
|
|
81
|
+
*/
|
|
82
|
+
getById(id) {
|
|
83
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
const fp = this.makeFilePath(id);
|
|
85
|
+
if (!(0, fs_1.existsSync)(fp))
|
|
86
|
+
throw ErrorManager_1.default.make('SS_STRUCT_NOT_FOUND', { id });
|
|
87
|
+
return ImportManager_1.default.importJSON(fp);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Updating the container structure
|
|
92
|
+
*
|
|
93
|
+
* @param id Container ID
|
|
94
|
+
* @param structure updated container structure object
|
|
95
|
+
*/
|
|
96
|
+
updateById(id, structure) {
|
|
97
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
+
const cStruct = yield this.getById(id);
|
|
99
|
+
this.updateStructure(cStruct, structure, id);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Updates the display structure parameter from the file structure
|
|
104
|
+
*
|
|
105
|
+
* @param cStruct now container structure
|
|
106
|
+
* @param structure new structure
|
|
107
|
+
*/
|
|
108
|
+
updateStructure(cStruct, structure, id) {
|
|
109
|
+
for (const dID in cStruct) {
|
|
110
|
+
if (structure[dID] && structure[dID].display)
|
|
111
|
+
cStruct[dID].display = structure[dID].display;
|
|
112
|
+
}
|
|
113
|
+
const fp = this.makeFilePath(id);
|
|
114
|
+
(0, fs_1.writeFileSync)(fp, JSON.stringify(cStruct));
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Forms the path to the structure file by its identifier
|
|
118
|
+
*
|
|
119
|
+
* @param id Container ID
|
|
120
|
+
*/
|
|
121
|
+
makeFilePath(id) {
|
|
122
|
+
return path_1.default.join(this.options.structureDir, id + '.json');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.default = StructureStorage;
|