vrack2-core 0.0.1 → 1.0.1
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 +33 -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 +311 -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 +15 -14
- 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 +346 -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
package/src/Container.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import EventEmitter from "events";
|
|
2
|
-
import DeviceManager from "./DeviceManager";
|
|
2
|
+
import DeviceManager from "./boot/DeviceManager";
|
|
3
3
|
|
|
4
4
|
import ErrorManager from "./errors/ErrorManager";
|
|
5
5
|
import IServiceStructure from "./IServiceStructure";
|
|
@@ -14,7 +14,15 @@ import DevicePort from "./service/DevicePort";
|
|
|
14
14
|
|
|
15
15
|
import IPort from "./ports/IPort";
|
|
16
16
|
import DeviceConnect from "./service/DeviceConnect";
|
|
17
|
+
import IAction from "./actions/IAction";
|
|
18
|
+
import Bootstrap from "./Bootstrap";
|
|
19
|
+
import IMetricSettings from "./metrics/IMetricSettings";
|
|
20
|
+
import BasicMetric from "./metrics/BasicMetric";
|
|
21
|
+
import IDeviceEvent from "./service/IDeviceEvent";
|
|
22
|
+
import Utility from "./Utility";
|
|
23
|
+
import { existsSync } from "fs";
|
|
17
24
|
|
|
25
|
+
/***** ******** DEVICE ERROR ********************/
|
|
18
26
|
|
|
19
27
|
ErrorManager.register('Container', 'FBDRkSAWnlcc', 'CTR_ERROR_INIT_DEVICE', 'Device initialization error', {
|
|
20
28
|
deviceConfig: Rule.object().description('Device configuration')
|
|
@@ -24,95 +32,375 @@ ErrorManager.register('Container', '96UX24PTyFU7', 'CTR_ERROR_INIT_CONNECTION',
|
|
|
24
32
|
connection: Rule.string().description('Connection string')
|
|
25
33
|
})
|
|
26
34
|
|
|
27
|
-
|
|
28
35
|
ErrorManager.register('Container', '0HVa3cO1E2vB', 'CTR_INCORRECT_DEVICE_ID', 'Incorrect device id', {})
|
|
29
36
|
ErrorManager.register('Container', 'uF62e07wloS9', 'CTR_DEVICE_DUBLICATE', 'Device id is dublicated', {})
|
|
30
37
|
ErrorManager.register('Container', '2RZznI3JDNUW', 'CTR_ERROR_PREPARE_OPTIONS', 'An error occurred while preparing options', {
|
|
31
38
|
message: Rule.string().description('Exception error string')
|
|
32
39
|
})
|
|
40
|
+
|
|
33
41
|
ErrorManager.register('Container', 'NDW2oD7mFxqB', 'CTR_DEVICE_ACTION_NF', 'Action on device not found', {
|
|
42
|
+
device: Rule.string().description('Device ID'),
|
|
34
43
|
action: Rule.string().description('Action name'),
|
|
35
|
-
method: Rule.string().description('Method name')
|
|
44
|
+
method: Rule.string().description('Method name'),
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
ErrorManager.register('Container', 'XOXLMVCN9OBI', 'CTR_DEVICE_NF', 'Device in container found', {
|
|
48
|
+
device: Rule.string().description('Device ID'),
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
ErrorManager.register('Container', '570RD59JEYVN', 'CTR_DEVICE_ACTION_HANDLER_NF', 'Device handler action not found', {
|
|
52
|
+
device: Rule.string().description('Device ID'),
|
|
53
|
+
action: Rule.string().description('Device action name'),
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
ErrorManager.register('Container', 'RJV0KT2DFZBZ', 'CTR_DEVICE_PROCESS_EXCEPTION', 'During process execution - the device threw an exception', {
|
|
57
|
+
device: Rule.string().description('Device ID'),
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
ErrorManager.register('Container', 'K65XWSYOBVFG', 'CTR_DEVICE_PROCESS_PROMISE_EXCEPTION', 'During processPromise execution - the device threw an exception', {
|
|
61
|
+
device: Rule.string().description('Device ID'),
|
|
36
62
|
})
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
/***** ******** PORTS ERROR ********************/
|
|
66
|
+
|
|
37
67
|
ErrorManager.register('Container', 'jkIpU1p4z5uz', 'CTR_INCORRECT_DYNAMIC_PN', 'Incorrect dynamic port name', {
|
|
38
68
|
port: Rule.string().description('Incorrect port name')
|
|
39
69
|
})
|
|
70
|
+
|
|
40
71
|
ErrorManager.register('Container', 'e8m8dUVVOEU7', 'CTR_INCORRECT_PN', 'Incorrect port name', {
|
|
41
72
|
port: Rule.string().description('Incorrect port name')
|
|
42
73
|
})
|
|
74
|
+
|
|
43
75
|
ErrorManager.register('Container', 'qPevPU6SRJ18', 'CTR_INPUT_HANDLER_NF', 'Port input handler not found', {
|
|
44
76
|
port: Rule.string().description('Port name for handler'),
|
|
45
77
|
handler: Rule.string().description('Handler name')
|
|
46
78
|
})
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
ErrorManager.register('Container', 'QlcUh744VzAG', 'CTR_DEVICE_PORT_NF', 'Port on device not found', {
|
|
82
|
+
port: Rule.string().description('Port name'),
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
/***** ******** CONNECTION ERROR ********************/
|
|
86
|
+
|
|
47
87
|
ErrorManager.register('Container', 'Kp74OuVGNU0u', 'CTR_CONNECTION_INCORRECT', 'Incorrect connection format', {
|
|
48
88
|
connection: Rule.string().description('Connection string'),
|
|
49
89
|
error: Rule.string().description('String of error problem'),
|
|
50
90
|
})
|
|
91
|
+
|
|
51
92
|
ErrorManager.register('Container', 'eMrJEISxvali', 'CTR_CONNECTION_DEVICE_NF', 'Connection device not found', {
|
|
52
93
|
connection: Rule.string().description('Connection string'),
|
|
53
94
|
device: Rule.string().description('Device name not found')
|
|
54
95
|
})
|
|
96
|
+
|
|
55
97
|
ErrorManager.register('Container', 'CwFj1G47H45E', 'CTR_CONNECTION_PORT_NF', 'Connection port not found', {
|
|
56
98
|
connection: Rule.string().description('Connection string'),
|
|
57
99
|
port: Rule.string().description('Port name not found')
|
|
58
100
|
})
|
|
59
101
|
|
|
102
|
+
ErrorManager.register('Container', 'XR1K10R0OOUC', 'CTR_INCOMPATIBLE_PORTS', 'Incompatible ports', {
|
|
103
|
+
connection: Rule.string().description('Connection string'),
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
ErrorManager.register('Container', 'MmVoDOQwaYkx', 'CTR_INCORRECT_BOOSTRAP', 'The required DeviceManager class is not specified correctly', {})
|
|
108
|
+
ErrorManager.register('Container', 'e090R0MLyb7y', 'CTR_CONF_EXTENDS_PROBLEM', 'Problem with extending service configuration.', {})
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Contains the structure of the service
|
|
113
|
+
*
|
|
114
|
+
* Where { DeviceID: DeviceStructure }
|
|
115
|
+
*/
|
|
116
|
+
export interface IContainerStructure {
|
|
117
|
+
[key: string]: {
|
|
118
|
+
/** Device ID */
|
|
119
|
+
id: string;
|
|
120
|
+
/** Device type like a 'vendor.Device'*/
|
|
121
|
+
type: string;
|
|
122
|
+
/** Actions list @see IAction */
|
|
123
|
+
actions: { [key: string]: IAction };
|
|
124
|
+
/** List of ports with their connections */
|
|
125
|
+
outputs: { [key: string]: Array<{ device: string, port: string }> };
|
|
126
|
+
/** List of ports with their connections */
|
|
127
|
+
inputs: { [key: string]: Array<{ device: string, port: string }> };
|
|
128
|
+
/** List of all ports on the device */
|
|
129
|
+
ports: Array<IDeviceStructurePort>;
|
|
130
|
+
/** A list of device metrics */
|
|
131
|
+
metrics: { [key: string]: IMetricSettings }
|
|
132
|
+
/** Device display settings */
|
|
133
|
+
settings: { [key: string]: any };
|
|
134
|
+
/** Personalized display settings */
|
|
135
|
+
display?: {
|
|
136
|
+
header_bg?: string,
|
|
137
|
+
body_bg?: string,
|
|
138
|
+
group_bg?: string,
|
|
139
|
+
is_rotated?: boolean,
|
|
140
|
+
row?: number,
|
|
141
|
+
col?: number
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
export interface IDeviceStructurePort extends IPort {
|
|
146
|
+
/** Port ID */
|
|
147
|
+
port: string,
|
|
148
|
+
/** Port direct */
|
|
149
|
+
direct: string,
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Service Load Class. It loads all devices in the list,
|
|
154
|
+
* establishes connections between them, and performs device startup.
|
|
155
|
+
*
|
|
156
|
+
* This class is a bit complicated for a simple description.
|
|
157
|
+
* It is recommended to familiarize yourself with the source code
|
|
158
|
+
*/
|
|
60
159
|
export default class Container extends EventEmitter {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
160
|
+
|
|
161
|
+
/** Unique service ID */
|
|
162
|
+
id = '';
|
|
163
|
+
|
|
164
|
+
/** List of devices in container */
|
|
165
|
+
devices: { [key: string]: Device } = {}
|
|
166
|
+
|
|
167
|
+
/** Parent container if it exists */
|
|
168
|
+
parent?: Container
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Path to extended conf file for init loading
|
|
172
|
+
* @see fillConfFile()
|
|
173
|
+
* */
|
|
174
|
+
confFile?: string
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Container bootstrap class
|
|
178
|
+
*
|
|
179
|
+
* A different bootstrap class must be created for each container
|
|
180
|
+
*/
|
|
181
|
+
Bootstrap: Bootstrap
|
|
182
|
+
|
|
183
|
+
/** inited flag */
|
|
184
|
+
protected inited = false
|
|
185
|
+
|
|
186
|
+
/** run flag */
|
|
187
|
+
protected runned = false
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Service structure config
|
|
191
|
+
*
|
|
192
|
+
* @see constructor
|
|
193
|
+
*/
|
|
194
|
+
protected service: IServiceStructure
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* List of all device actions
|
|
198
|
+
*
|
|
199
|
+
* [deviceID]: { action.name: BasicAction}
|
|
200
|
+
*/
|
|
64
201
|
protected deviceActions: { [key: string]: { [key: string]: BasicAction } }
|
|
65
202
|
|
|
66
|
-
|
|
203
|
+
/**
|
|
204
|
+
* List of all device metrics
|
|
205
|
+
*
|
|
206
|
+
*/
|
|
207
|
+
protected deviceMetrics: { [key: string]: { [key: string]: BasicMetric } }
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Container structure
|
|
211
|
+
*/
|
|
212
|
+
protected structure: IContainerStructure = {}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Create container needed service structure & device manager
|
|
216
|
+
*
|
|
217
|
+
* @param service Service structure
|
|
218
|
+
* @param bootstrap Bootstrap class Object
|
|
219
|
+
*
|
|
220
|
+
* */
|
|
221
|
+
constructor(id: string, service: IServiceStructure, Bootstrap: Bootstrap, confFile?: string) {
|
|
67
222
|
super()
|
|
68
|
-
this.
|
|
69
|
-
this.
|
|
223
|
+
this.id = id
|
|
224
|
+
this.service = service
|
|
70
225
|
this.deviceActions = {}
|
|
226
|
+
this.deviceMetrics = {}
|
|
227
|
+
this.confFile = confFile
|
|
228
|
+
this.Bootstrap = Bootstrap
|
|
71
229
|
}
|
|
72
230
|
|
|
231
|
+
/**
|
|
232
|
+
* Run container
|
|
233
|
+
*/
|
|
73
234
|
async run() {
|
|
235
|
+
await this.init()
|
|
236
|
+
await this.runProcess()
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Extends service from config file
|
|
241
|
+
*
|
|
242
|
+
* Sometimes there is a need to override the settings of some devices.
|
|
243
|
+
* To do this, you can use a special configuration file of the service.
|
|
244
|
+
* It contains the same as the main service file and replaces with its settings
|
|
245
|
+
* and parameters the settings and parameters of the main service.
|
|
246
|
+
*
|
|
247
|
+
* @see init()
|
|
248
|
+
*/
|
|
249
|
+
protected fillConfFile() {
|
|
250
|
+
if (!this.confFile || !existsSync(this.confFile)) return
|
|
251
|
+
const conf = ImportManager.importJSON(this.confFile)
|
|
252
|
+
if (conf.devices === undefined || !Array.isArray(conf.devices)) conf.devices = []
|
|
253
|
+
for (const device of conf.devices) {
|
|
254
|
+
if (!device.id || device.options === undefined || typeof device.options !== 'object') continue
|
|
255
|
+
for (const cdev of this.service.devices) {
|
|
256
|
+
if (cdev.id === device.id) {
|
|
257
|
+
for (const pname in device.options) cdev.options[pname] = device.options[pname]
|
|
258
|
+
if (device.connections) cdev.connections = device.connections
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
74
264
|
|
|
75
|
-
|
|
265
|
+
/**
|
|
266
|
+
* Creates device classes. Preprocesses the device,
|
|
267
|
+
* then adds ports to it and creates connections between ports.
|
|
268
|
+
*
|
|
269
|
+
* When adding and creating devices, ports and connections,
|
|
270
|
+
* the service structure is also created
|
|
271
|
+
*
|
|
272
|
+
* 1. Init device
|
|
273
|
+
* 2. Init individual device connections
|
|
274
|
+
* 3. Init other connections
|
|
275
|
+
*
|
|
276
|
+
* @see structure
|
|
277
|
+
*/
|
|
278
|
+
async init() {
|
|
279
|
+
if (this.inited) return
|
|
280
|
+
this.inited = true
|
|
281
|
+
this.emit('configure')
|
|
282
|
+
try {
|
|
283
|
+
this.fillConfFile()
|
|
284
|
+
} catch (err) {
|
|
285
|
+
if (err instanceof Error) {
|
|
286
|
+
const ner = ErrorManager.make('CTR_CONF_EXTENDS_PROBLEM', {}).setTrace(err as Error).add(err)
|
|
287
|
+
throw ner
|
|
288
|
+
}
|
|
289
|
+
throw err
|
|
290
|
+
}
|
|
291
|
+
this.emit('beforeInit')
|
|
292
|
+
this.emit('init')
|
|
293
|
+
for (const device of this.service.devices) {
|
|
76
294
|
try {
|
|
295
|
+
this.emit('initDevice', device)
|
|
77
296
|
await this.initDevice(device)
|
|
78
|
-
} catch (error) {
|
|
297
|
+
} catch (error ) {
|
|
79
298
|
const ner = ErrorManager.make('CTR_ERROR_INIT_DEVICE', { deviceConfig: device })
|
|
80
|
-
|
|
299
|
+
ner.add(error as Error)
|
|
81
300
|
throw ner
|
|
82
301
|
}
|
|
83
302
|
}
|
|
303
|
+
this.emit('afterInit')
|
|
304
|
+
this.emit('beforeConnections')
|
|
305
|
+
this.emit('connections')
|
|
306
|
+
for (const device of this.service.devices) {
|
|
307
|
+
if (!device.connections) continue
|
|
308
|
+
for (const conn of device.connections) {
|
|
309
|
+
this.emit('connection',conn)
|
|
310
|
+
this.initConnection(conn)
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (Array.isArray(this.service.connections)) {
|
|
315
|
+
for (const conn of this.service.connections) {
|
|
316
|
+
|
|
317
|
+
this.initConnection(conn)
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
this.emit('afterConnections')
|
|
321
|
+
}
|
|
84
322
|
|
|
85
|
-
|
|
323
|
+
/**
|
|
324
|
+
* Run process & processPromise of all devices
|
|
325
|
+
*/
|
|
326
|
+
async runProcess() {
|
|
327
|
+
if (this.runned) return
|
|
328
|
+
this.runned = true
|
|
329
|
+
this.emit('beforeProcess')
|
|
330
|
+
for (const key in this.devices) {
|
|
86
331
|
try {
|
|
87
|
-
|
|
332
|
+
this.emit('process',key)
|
|
333
|
+
this.devices[key].process()
|
|
88
334
|
} catch (error) {
|
|
89
|
-
|
|
90
|
-
if (error instanceof CoreError) ner.add(error)
|
|
91
|
-
throw ner
|
|
335
|
+
throw ErrorManager.make('CTR_DEVICE_PROCESS_EXCEPTION', { device: key }).add(error as Error)
|
|
92
336
|
}
|
|
93
337
|
}
|
|
338
|
+
this.emit('afterProcess')
|
|
339
|
+
this.emit('beforeProcessPromise')
|
|
340
|
+
for (const key in this.devices) {
|
|
341
|
+
try {
|
|
342
|
+
this.emit('processPromise', key)
|
|
343
|
+
await this.devices[key].processPromise()
|
|
344
|
+
} catch (error) {
|
|
345
|
+
throw ErrorManager.make('CTR_DEVICE_PROCESS_PROMISE_EXCEPTION', { device: key }).add(error as Error)
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
this.emit('afterProcessPromise')
|
|
349
|
+
this.emit('beforeLoaded')
|
|
350
|
+
this.emit('loaded')
|
|
351
|
+
}
|
|
94
352
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
353
|
+
/**
|
|
354
|
+
* Check device action and run him
|
|
355
|
+
*
|
|
356
|
+
* @param device Device ID
|
|
357
|
+
* @param action Device action (as 'action.name')
|
|
358
|
+
* @param data Data for action
|
|
359
|
+
*/
|
|
360
|
+
async deviceAction(device: string, action: string, data: any) {
|
|
361
|
+
if (!this.deviceActions[device]) throw ErrorManager.make('CTR_DEVICE_NF', { device })
|
|
362
|
+
const deviceClass = this.devices[device]
|
|
363
|
+
const deviceActions = this.deviceActions[device]
|
|
364
|
+
const method = ImportManager.camelize('action.' + action)
|
|
365
|
+
if (!deviceActions[action]) throw ErrorManager.make('CTR_DEVICE_ACTION_NF', { device, action, method })
|
|
366
|
+
if (!deviceClass[method as keyof Device]) throw ErrorManager.make('CTR_DEVICE_ACTION_HANDLER_NF', { device, action })
|
|
367
|
+
const actionExport = deviceActions[action].exportRaw()
|
|
368
|
+
Validator.validate(actionExport.requirements, data)
|
|
369
|
+
return await deviceClass[method as keyof Device](data)
|
|
103
370
|
}
|
|
104
371
|
|
|
372
|
+
/**
|
|
373
|
+
* Return structure
|
|
374
|
+
*/
|
|
375
|
+
async getStructure() {
|
|
376
|
+
return this.structure
|
|
377
|
+
}
|
|
105
378
|
|
|
379
|
+
/**
|
|
380
|
+
* Init one device
|
|
381
|
+
*
|
|
382
|
+
* 1. Make device class object
|
|
383
|
+
* 2. Fill device options
|
|
384
|
+
* 3. Run device prepareOptions method
|
|
385
|
+
* 4. Validating device options
|
|
386
|
+
* 5. Check device actions
|
|
387
|
+
* 6. make device inputs ports
|
|
388
|
+
* 7. make device outputs ports
|
|
389
|
+
**/
|
|
106
390
|
protected async initDevice(dconf: IStructureDevice) {
|
|
107
|
-
const
|
|
391
|
+
const DM = this.Bootstrap.getBootClass('DeviceManager', DeviceManager) as DeviceManager
|
|
392
|
+
const cs = await DM.get(dconf.type)
|
|
108
393
|
//
|
|
109
|
-
if (dconf.id === undefined || !dconf.id || typeof dconf.id !== 'string') {
|
|
394
|
+
if (dconf.id === undefined || !dconf.id || typeof dconf.id !== 'string' || !Utility.isDeviceName(dconf.id)) {
|
|
110
395
|
throw ErrorManager.make('CTR_INCORRECT_DEVICE_ID')
|
|
111
396
|
}
|
|
112
397
|
// Device id is dublicated
|
|
113
398
|
if (dconf.id in this.devices) throw ErrorManager.make('CTR_DEVICE_DUBLICATE')
|
|
399
|
+
|
|
400
|
+
// Create device
|
|
114
401
|
const dev = new cs(dconf.id, dconf.type, this) as Device
|
|
115
402
|
this.devices[dconf.id] = dev
|
|
403
|
+
|
|
116
404
|
// Fill options
|
|
117
405
|
for (const key in dconf.options) dev.options[key] = dconf.options[key]
|
|
118
406
|
|
|
@@ -130,7 +418,19 @@ export default class Container extends EventEmitter {
|
|
|
130
418
|
const rules = dev.checkOptions()
|
|
131
419
|
// Validating
|
|
132
420
|
Validator.validate(rules, dev.options)
|
|
133
|
-
|
|
421
|
+
|
|
422
|
+
/** create structure */
|
|
423
|
+
this.structure[dconf.id] = {
|
|
424
|
+
id: dconf.id,
|
|
425
|
+
type: dconf.type,
|
|
426
|
+
actions: {},
|
|
427
|
+
outputs: {},
|
|
428
|
+
inputs: {},
|
|
429
|
+
ports: [],
|
|
430
|
+
settings: {},
|
|
431
|
+
metrics: {},
|
|
432
|
+
}
|
|
433
|
+
|
|
134
434
|
dev.preProcess()
|
|
135
435
|
|
|
136
436
|
// Check actions
|
|
@@ -138,11 +438,20 @@ export default class Container extends EventEmitter {
|
|
|
138
438
|
for (const action in this.deviceActions[dev.id]) {
|
|
139
439
|
const method = ImportManager.camelize('action.' + action)
|
|
140
440
|
if (!(method in dev)) throw ErrorManager.make('CTR_DEVICE_ACTION_NF', { action, method })
|
|
441
|
+
// add structure device action
|
|
442
|
+
this.structure[dconf.id].actions[action] = this.deviceActions[dev.id][action].export()
|
|
141
443
|
}
|
|
142
444
|
|
|
445
|
+
this.structure[dconf.id].settings = dev.settings()
|
|
143
446
|
|
|
144
|
-
//
|
|
145
|
-
|
|
447
|
+
// Make Metrics
|
|
448
|
+
this.deviceMetrics[dev.id] = dev.metrics()
|
|
449
|
+
for (const metric in this.deviceMetrics[dev.id]) {
|
|
450
|
+
const raw = this.deviceMetrics[dev.id][metric].export()
|
|
451
|
+
const nEvent: IDeviceEvent = { device: dev.id, data: metric, trace: raw }
|
|
452
|
+
this.emit('device.register.metric', nEvent)
|
|
453
|
+
this.structure[dconf.id].metrics[metric] = raw
|
|
454
|
+
}
|
|
146
455
|
|
|
147
456
|
// make inputPorts
|
|
148
457
|
const iPorts = dev.inputs()
|
|
@@ -152,13 +461,19 @@ export default class Container extends EventEmitter {
|
|
|
152
461
|
for (const subkey in pList) {
|
|
153
462
|
this.checkPortName(subkey)
|
|
154
463
|
const handler = ImportManager.camelize('input.' + subkey) as keyof Device
|
|
155
|
-
this.checkInputHandler(subkey, handler
|
|
464
|
+
this.checkInputHandler(subkey, handler, dev)
|
|
156
465
|
const ndp = new DevicePort(subkey, pList[subkey])
|
|
157
466
|
dev.ports.input[subkey] = ndp
|
|
467
|
+
// add structure device input ports
|
|
468
|
+
this.structure[dconf.id].inputs[subkey] = []
|
|
469
|
+
this.structure[dconf.id].ports.push(
|
|
470
|
+
Object.assign({ port: subkey, direct: 'input' }, pList[subkey])
|
|
471
|
+
)
|
|
158
472
|
if (handler in dev) ndp.push = dev[handler].bind(dev)
|
|
159
473
|
}
|
|
160
474
|
}
|
|
161
475
|
|
|
476
|
+
// make output ports
|
|
162
477
|
const oPorts = dev.outputs()
|
|
163
478
|
for (const key in oPorts) {
|
|
164
479
|
const exp = oPorts[key].export()
|
|
@@ -167,26 +482,63 @@ export default class Container extends EventEmitter {
|
|
|
167
482
|
this.checkPortName(subkey)
|
|
168
483
|
const ndp = new DevicePort(subkey, pList[subkey])
|
|
169
484
|
dev.ports.output[subkey] = ndp
|
|
485
|
+
// add structure device output ports
|
|
486
|
+
this.structure[dconf.id].outputs[subkey] = []
|
|
487
|
+
this.structure[dconf.id].ports.push(
|
|
488
|
+
Object.assign({ port: subkey, direct: 'output' }, pList[subkey])
|
|
489
|
+
)
|
|
170
490
|
}
|
|
171
491
|
}
|
|
172
492
|
}
|
|
173
493
|
|
|
174
|
-
|
|
494
|
+
/**
|
|
495
|
+
* Check device input handler
|
|
496
|
+
* Make CTR_INPUT_HANDLER_NF error if not exists
|
|
497
|
+
* @see initDevice make inputPorts
|
|
498
|
+
*/
|
|
499
|
+
protected checkInputHandler(port: string, handler: string, device: Device) {
|
|
175
500
|
if (!(handler in device)) throw ErrorManager.make('CTR_INPUT_HANDLER_NF', { port, handler })
|
|
176
501
|
}
|
|
177
502
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Init device connection
|
|
506
|
+
*
|
|
507
|
+
* @param conn Device connection string like a "DevID.port -> DevIDTO.port"
|
|
508
|
+
*/
|
|
509
|
+
protected initConnection(conn: string) {
|
|
510
|
+
try {
|
|
511
|
+
const cc = this.toConnection(conn)
|
|
512
|
+
this.emit('connection',cc)
|
|
513
|
+
if (!(cc.outputDevice in this.devices)) throw ErrorManager.make('CTR_CONNECTION_DEVICE_NF', { connection: conn, device: cc.outputDevice })
|
|
514
|
+
if (!(cc.outputPort in this.devices[cc.outputDevice].ports.output)) throw ErrorManager.make('CTR_CONNECTION_PORT_NF', { connection: conn, port: cc.outputPort })
|
|
515
|
+
|
|
516
|
+
if (!(cc.inputDevice in this.devices)) throw ErrorManager.make('CTR_CONNECTION_DEVICE_NF', { connection: conn, device: cc.inputDevice })
|
|
517
|
+
if (!(cc.inputPort in this.devices[cc.inputDevice].ports.input)) throw ErrorManager.make('CTR_CONNECTION_PORT_NF', { connection: conn, port: cc.inputPort })
|
|
518
|
+
|
|
519
|
+
if (this.devices[cc.inputDevice].ports.input[cc.inputPort].type !== this.devices[cc.outputDevice].ports.output[cc.outputPort].type) throw ErrorManager.make('CTR_INCOMPATIBLE_PORTS', { connection: conn })
|
|
520
|
+
|
|
521
|
+
const outPort = this.devices[cc.outputDevice].ports.output[cc.outputPort]
|
|
522
|
+
const inPort = this.devices[cc.inputDevice].ports.input[cc.inputPort]
|
|
523
|
+
|
|
524
|
+
// Set structure connections
|
|
525
|
+
if (this.structure[cc.outputDevice].outputs[cc.outputPort] === undefined) this.structure[cc.outputDevice].outputs[cc.outputPort] = []
|
|
526
|
+
this.structure[cc.outputDevice].outputs[cc.outputPort].push({ device: cc.inputDevice, port: cc.inputPort })
|
|
527
|
+
if (this.structure[cc.inputDevice].inputs[cc.inputPort] === undefined) this.structure[cc.inputDevice].inputs[cc.inputPort] = []
|
|
528
|
+
this.structure[cc.inputDevice].inputs[cc.inputPort].push({ device: cc.outputDevice, port: cc.outputPort })
|
|
529
|
+
new DeviceConnect(outPort, inPort)
|
|
530
|
+
} catch (error) {
|
|
531
|
+
const ner = ErrorManager.make('CTR_ERROR_INIT_CONNECTION', { connection: conn })
|
|
532
|
+
if (error instanceof CoreError) ner.add(error)
|
|
533
|
+
throw ner
|
|
534
|
+
}
|
|
188
535
|
}
|
|
189
536
|
|
|
537
|
+
/**
|
|
538
|
+
* Container Helper - parse connection string to format object
|
|
539
|
+
*
|
|
540
|
+
* @return Connection object
|
|
541
|
+
*/
|
|
190
542
|
private toConnection(con: string) {
|
|
191
543
|
const act = con.split('->')
|
|
192
544
|
if (act.length !== 2) throw ErrorManager.make('CTR_CONNECTION_INCORRECT', { connection: con, error: "Syntax connection error, syntax have -> beetwen device" })
|
|
@@ -205,16 +557,32 @@ export default class Container extends EventEmitter {
|
|
|
205
557
|
if (outputDevice === undefined) outputDevice = ''
|
|
206
558
|
if (inputDevice === undefined) inputDevice = ''
|
|
207
559
|
|
|
208
|
-
const result: {
|
|
560
|
+
const result: {
|
|
561
|
+
outputDevice: string,
|
|
562
|
+
outputPort: string,
|
|
563
|
+
inputDevice: string,
|
|
564
|
+
inputPort: string,
|
|
565
|
+
} = {
|
|
209
566
|
outputDevice, outputPort, inputDevice, inputPort
|
|
210
567
|
}
|
|
211
568
|
return result
|
|
212
569
|
}
|
|
213
570
|
|
|
571
|
+
/**
|
|
572
|
+
* Check Port name (strict format a-zA-Z0-9.)
|
|
573
|
+
*
|
|
574
|
+
* @param port Port name
|
|
575
|
+
*/
|
|
214
576
|
protected checkPortName(port: string) {
|
|
215
577
|
if (!port.match(/[a-zA-Z0-9.]/)) throw ErrorManager.make('CTR_INCORRECT_PN', { port })
|
|
216
578
|
}
|
|
217
579
|
|
|
580
|
+
/**
|
|
581
|
+
* Convert dynamic port to ports list
|
|
582
|
+
*
|
|
583
|
+
* @param name Port name with %d symbols
|
|
584
|
+
* @param iPort IPort object (port settings)
|
|
585
|
+
*/
|
|
218
586
|
protected getPortList(name: string, iPort: IPort) {
|
|
219
587
|
const result: { [key: string]: IPort } = {}
|
|
220
588
|
if (!iPort.dynamic) {
|
package/src/IServiceStructure.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import IStructureDevice from "./IStructureDevice"
|
|
2
2
|
|
|
3
|
+
/** Basic service file structure */
|
|
3
4
|
export default interface IServiceStructure {
|
|
5
|
+
/**
|
|
6
|
+
* Devices list
|
|
7
|
+
* @see IStructureDevice
|
|
8
|
+
*/
|
|
4
9
|
devices: Array<IStructureDevice>
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Connections list
|
|
13
|
+
*/
|
|
5
14
|
connections: Array<string>
|
|
6
15
|
}
|
package/src/IStructureDevice.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export default interface IStructureDevice {
|
|
2
|
+
/** Device ID */
|
|
2
3
|
id: string;
|
|
4
|
+
/** Device type in VRack style like a 'vendor.Device' */
|
|
3
5
|
type: string;
|
|
6
|
+
/** Device options */
|
|
4
7
|
options: { [key: string]: any; };
|
|
8
|
+
/** Device connections */
|
|
9
|
+
connections?: Array<string>
|
|
5
10
|
}
|