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.
Files changed (148) hide show
  1. package/README.md +25 -4
  2. package/docs/Bootstrap.md +77 -0
  3. package/docs/Container.md +124 -0
  4. package/docs/Device.md +272 -0
  5. package/docs/FastStart.md +111 -0
  6. package/docs/Structure.md +148 -0
  7. package/lib/Bootstrap.d.ts +79 -0
  8. package/lib/Bootstrap.js +103 -0
  9. package/lib/Container.d.ts +202 -6
  10. package/lib/Container.js +295 -27
  11. package/lib/IServiceStructure.d.ts +8 -0
  12. package/lib/IStructureDevice.d.ts +5 -0
  13. package/lib/ImportManager.d.ts +85 -3
  14. package/lib/ImportManager.js +122 -16
  15. package/lib/MainProcess.d.ts +30 -3
  16. package/lib/MainProcess.js +28 -6
  17. package/lib/Utility.d.ts +15 -21
  18. package/lib/Utility.js +40 -40
  19. package/lib/actions/Action.d.ts +10 -0
  20. package/lib/actions/Action.js +10 -0
  21. package/lib/actions/BasicAction.d.ts +60 -0
  22. package/lib/actions/BasicAction.js +62 -0
  23. package/lib/actions/GlobalAction.d.ts +5 -0
  24. package/lib/actions/GlobalAction.js +5 -0
  25. package/lib/actions/IAction.d.ts +7 -0
  26. package/lib/actions/ILocalAction.d.ts +7 -0
  27. package/lib/boot/BootClass.d.ts +93 -0
  28. package/lib/boot/BootClass.js +101 -0
  29. package/lib/boot/DeviceFileStorage.d.ts +38 -0
  30. package/lib/boot/DeviceFileStorage.js +112 -0
  31. package/lib/boot/DeviceManager.d.ts +190 -0
  32. package/lib/boot/DeviceManager.js +306 -0
  33. package/lib/boot/DeviceMetrics.d.ts +82 -0
  34. package/lib/boot/DeviceMetrics.js +128 -0
  35. package/lib/boot/StructureStorage.d.ts +59 -0
  36. package/lib/boot/StructureStorage.js +125 -0
  37. package/lib/errors/CoreError.d.ts +42 -25
  38. package/lib/errors/CoreError.js +44 -24
  39. package/lib/errors/ErrorManager.d.ts +18 -20
  40. package/lib/errors/ErrorManager.js +23 -22
  41. package/lib/index.d.ts +20 -4
  42. package/lib/index.js +28 -4
  43. package/lib/metrics/BasicMetric.d.ts +49 -0
  44. package/lib/metrics/BasicMetric.js +79 -0
  45. package/lib/metrics/IMetricSettings.d.ts +32 -0
  46. package/lib/metrics/IMetricSettings.js +2 -0
  47. package/lib/metrics/IvMs.d.ts +9 -0
  48. package/lib/metrics/IvMs.js +22 -0
  49. package/lib/metrics/IvS.d.ts +9 -0
  50. package/lib/metrics/IvS.js +22 -0
  51. package/lib/metrics/IvUs.d.ts +9 -0
  52. package/lib/metrics/IvUs.js +22 -0
  53. package/lib/metrics/Metric.d.ts +17 -0
  54. package/lib/metrics/Metric.js +27 -0
  55. package/lib/ports/BasicPort.d.ts +39 -0
  56. package/lib/ports/BasicPort.js +39 -0
  57. package/lib/ports/ILocalPort.d.ts +7 -0
  58. package/lib/ports/IPort.d.ts +7 -0
  59. package/lib/ports/Port.d.ts +10 -0
  60. package/lib/ports/Port.js +10 -0
  61. package/lib/ports/ReturnPort.d.ts +5 -0
  62. package/lib/ports/ReturnPort.js +5 -0
  63. package/lib/service/Device.d.ts +213 -78
  64. package/lib/service/Device.js +185 -83
  65. package/lib/service/DeviceConnect.d.ts +4 -8
  66. package/lib/service/DeviceConnect.js +4 -8
  67. package/lib/service/DevicePort.d.ts +15 -6
  68. package/lib/service/DevicePort.js +29 -12
  69. package/lib/service/IDeviceEvent.d.ts +4 -1
  70. package/lib/validator/IValidationProblem.d.ts +7 -0
  71. package/lib/validator/IValidationRule.d.ts +12 -0
  72. package/lib/validator/IValidationSubrule.d.ts +2 -0
  73. package/lib/validator/Rule.d.ts +6 -2
  74. package/lib/validator/Rule.js +12 -2
  75. package/lib/validator/Validator.d.ts +48 -3
  76. package/lib/validator/Validator.js +70 -18
  77. package/lib/validator/types/AnyType.d.ts +17 -0
  78. package/lib/validator/types/AnyType.js +34 -0
  79. package/lib/validator/types/ArrayType.d.ts +37 -4
  80. package/lib/validator/types/ArrayType.js +42 -6
  81. package/lib/validator/types/BasicType.d.ts +67 -7
  82. package/lib/validator/types/BasicType.js +74 -8
  83. package/lib/validator/types/BooleanType.d.ts +23 -0
  84. package/lib/validator/types/BooleanType.js +47 -0
  85. package/lib/validator/types/FunctionType.d.ts +17 -0
  86. package/lib/validator/types/FunctionType.js +38 -0
  87. package/lib/validator/types/NumberType.d.ts +40 -5
  88. package/lib/validator/types/NumberType.js +53 -14
  89. package/lib/validator/types/ObjectType.d.ts +32 -5
  90. package/lib/validator/types/ObjectType.js +42 -8
  91. package/lib/validator/types/StringType.d.ts +30 -5
  92. package/lib/validator/types/StringType.js +33 -7
  93. package/package.json +10 -9
  94. package/src/Bootstrap.ts +122 -0
  95. package/src/Container.ts +411 -43
  96. package/src/IServiceStructure.ts +9 -0
  97. package/src/IStructureDevice.ts +5 -0
  98. package/src/ImportManager.ts +119 -11
  99. package/src/MainProcess.ts +53 -8
  100. package/src/Utility.ts +35 -36
  101. package/src/actions/Action.ts +12 -0
  102. package/src/actions/BasicAction.ts +63 -0
  103. package/src/actions/GlobalAction.ts +5 -0
  104. package/src/actions/IAction.ts +7 -0
  105. package/src/actions/ILocalAction.ts +7 -0
  106. package/src/boot/BootClass.ts +117 -0
  107. package/src/boot/DeviceFileStorage.ts +96 -0
  108. package/src/boot/DeviceManager.ts +339 -0
  109. package/src/boot/DeviceMetrics.ts +129 -0
  110. package/src/boot/StructureStorage.ts +108 -0
  111. package/src/errors/CoreError.ts +52 -26
  112. package/src/errors/ErrorManager.ts +46 -33
  113. package/src/index.ts +30 -6
  114. package/src/metrics/BasicMetric.ts +84 -0
  115. package/src/metrics/IMetricSettings.ts +38 -0
  116. package/src/metrics/IvMs.ts +18 -0
  117. package/src/metrics/IvS.ts +18 -0
  118. package/src/metrics/IvUs.ts +17 -0
  119. package/src/metrics/Metric.ts +25 -0
  120. package/src/ports/BasicPort.ts +39 -0
  121. package/src/ports/ILocalPort.ts +7 -0
  122. package/src/ports/IPort.ts +7 -0
  123. package/src/ports/Port.ts +11 -1
  124. package/src/ports/ReturnPort.ts +5 -0
  125. package/src/service/Device.ts +234 -103
  126. package/src/service/DeviceConnect.ts +4 -8
  127. package/src/service/DevicePort.ts +30 -11
  128. package/src/service/IDeviceEvent.ts +4 -1
  129. package/src/validator/IValidationProblem.ts +7 -0
  130. package/src/validator/IValidationRule.ts +12 -0
  131. package/src/validator/IValidationSubrule.ts +3 -0
  132. package/src/validator/Rule.ts +16 -2
  133. package/src/validator/Validator.ts +74 -23
  134. package/src/validator/types/AnyType.ts +32 -0
  135. package/src/validator/types/ArrayType.ts +43 -7
  136. package/src/validator/types/BasicType.ts +78 -9
  137. package/src/validator/types/BooleanType.ts +49 -0
  138. package/src/validator/types/FunctionType.ts +39 -0
  139. package/src/validator/types/NumberType.ts +53 -15
  140. package/src/validator/types/ObjectType.ts +52 -14
  141. package/src/validator/types/StringType.ts +34 -10
  142. package/docs/RU-README.md +0 -6
  143. package/lib/DeviceManager.d.ts +0 -32
  144. package/lib/DeviceManager.js +0 -143
  145. package/lib/test.d.ts +0 -1
  146. package/lib/test.js +0 -58
  147. package/src/DeviceManager.ts +0 -124
  148. 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
- protected config: IServiceStructure
62
- protected DeviceManager: DeviceManager
63
- protected devices: { [key: string]: Device } = {}
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
- constructor(config: IServiceStructure, dm: DeviceManager) {
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.config = config
69
- this.DeviceManager = dm
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
- for (const device of this.config.devices) {
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
- if (error instanceof CoreError) ner.add(error)
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
- for (const conn of this.config.connections) {
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
- await this.initConnection(conn)
332
+ this.emit('process',key)
333
+ this.devices[key].process()
88
334
  } catch (error) {
89
- const ner = ErrorManager.make('CTR_ERROR_INIT_CONNECTION', { connection: conn })
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
- for (const key in this.devices) this.devices[key].process()
96
- for (const key in this.devices) await this.devices[key].processPromise()
97
-
98
-
99
- // const cs = await this.DeviceManager.get('vrack.Master')
100
- // const cse = new cs()
101
- // console.log(cse)
102
- // cse.run()
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 cs = await this.DeviceManager.get(dconf.type)
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
- // make ports
145
- // prepare ports
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 , dev)
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
- protected checkInputHandler(port: string, handler:string, device: Device) {
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
- protected async initConnection(conn: string) {
179
- const cc = this.toConnection(conn)
180
- if (!(cc.outputDevice in this.devices)) throw ErrorManager.make('CTR_CONNECTION_DEVICE_NF', { connection: conn, device: cc.outputDevice })
181
- if (!(cc.outputPort in this.devices[cc.outputDevice].ports.output)) throw ErrorManager.make('CTR_CONNECTION_PORT_NF', { connection: conn, port: cc.outputPort })
182
-
183
- if (!(cc.inputDevice in this.devices)) throw ErrorManager.make('CTR_CONNECTION_DEVICE_NF', { connection: conn, device: cc.inputDevice })
184
- if (!(cc.inputPort in this.devices[cc.inputDevice].ports.input)) throw ErrorManager.make('CTR_CONNECTION_PORT_NF', { connection: conn, port: cc.inputPort })
185
- const outPort =this.devices[cc.outputDevice].ports.output[cc.outputPort]
186
- const inPort = this.devices[cc.inputDevice].ports.input[cc.inputPort]
187
- new DeviceConnect(outPort, inPort)
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: { [key: string]: string } = {
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) {
@@ -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
  }
@@ -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
  }