@amigo9090/ih-libiec61850-node 1.0.26 → 1.0.28

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.
@@ -1,4 +1,4 @@
1
- const { MmsClient } = require('../build/Release/addon_iec61850');
1
+ /*const { MmsClient } = require('../build/Release/addon_iec61850');
2
2
  const util = require('util');
3
3
 
4
4
  const client = new MmsClient((event, data) => {
@@ -21,27 +21,28 @@ const client = new MmsClient((event, data) => {
21
21
  });
22
22
  });
23
23
 
24
- // Чтение датасетов напрямую без промисов
25
- console.log('Reading datasets...');
26
- dataSets.forEach(ds => {
27
- console.log(`- ${ds.reference}`);
28
- client.readDataSetValues(ds.reference);
29
- });
24
+ // Чтение датасетов
25
+ console.log('Reading datasets in batch...');
26
+ const dataSetRefs = dataSets.map(ds => ds.reference);
27
+ client.readDataSetValues(dataSetRefs);
30
28
 
31
- // Чтение данных
29
+ // Чтение одиночного DataSet:
30
+ // client.readDataSetValues('WAGO61850ServerDevice/LLN0.DataSet01');
31
+
32
+ // Пакетное чтение данных
32
33
  console.log('Reading data...');
33
34
  const dataRefs = [
34
35
  'WAGO61850ServerDevice/XCBR1.Pos.stVal',
35
36
  'WAGO61850ServerDevice/GGIO1.Ind.stVal',
36
- 'WAGO61850ServerDevice/CALH1.GrAlm.stVal'
37
+ 'WAGO61850ServerDevice/CALH1.GrAlm.stVal'
37
38
  ];
38
- dataRefs.forEach(ref => client.readData(ref));
39
+ client.readData(dataRefs);
39
40
 
40
41
  // Включение отчётов
41
42
  const rcbRef = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0101';
42
43
  const dataSetRef = 'WAGO61850ServerDevice/LLN0.DataSet01';
43
44
  console.log(`Enabling reporting for ${rcbRef} with dataset ${dataSetRef}`);
44
- client.enableReporting(rcbRef, dataSetRef);
45
+ client.enableReporting(rcbRef, dataSetRef);
45
46
  })
46
47
  .catch(err => console.error('Error browsing data model:', err.message));
47
48
  }
@@ -54,7 +55,18 @@ const client = new MmsClient((event, data) => {
54
55
  } else if (data.event === 'dataModel') {
55
56
  console.log(`Data Model received: ${util.inspect(data.dataModel, { depth: null })}`);
56
57
  } else if (data.event === 'dataSet') {
57
- console.log(`DataSet received for ${data.dataSetRef}: ${util.inspect(data.value, { depth: null })}`);
58
+ // Одиночный DataSet (обратная совместимость)
59
+ console.log(`DataSet received for ${data.datasetRef}: ${util.inspect(data.value, { depth: null })}`);
60
+ } else if (data.event === 'multipleDataSets') {
61
+ // Множественные DataSet
62
+ console.log(`Multiple DataSets received for ${util.inspect(data.datasetRefs, { depth: null })}:`);
63
+ data.values.forEach((value, index) => {
64
+ if (value.isValid !== false) {
65
+ console.log(` DataSet[${index}]: ${data.datasetRefs[index]}, Value: ${util.inspect(value, { depth: null })}`);
66
+ } else {
67
+ console.log(` DataSet[${index}]: ${data.datasetRefs[index]}, Error: ${value.errorReason}`);
68
+ }
69
+ });
58
70
  } else if (data.event === 'report') {
59
71
  console.log(`Report received for ${data.rcbRef} (rptId: ${data.rptId}):`);
60
72
  if (data.timestamp) {
@@ -65,6 +77,15 @@ const client = new MmsClient((event, data) => {
65
77
  console.log(` Value[${index}]: ${util.inspect(value, { depth: null })}, Reason: ${data.reasonsForInclusion[index]}`);
66
78
  }
67
79
  });
80
+ } else if (data.event === 'batchData') {
81
+ console.log(`Batch Data received for ${util.inspect(data.dataRefs, { depth: null })}:`);
82
+ data.values.forEach((result, index) => {
83
+ if (result.isValid) {
84
+ console.log(` dataRef[${index}]: ${data.dataRefs[index]}, Value: ${util.inspect(result.value, { depth: null })}`);
85
+ } else {
86
+ console.log(` dataRef[${index}]: ${data.dataRefs[index]}, Error: ${result.errorReason}`);
87
+ }
88
+ });
68
89
  } else {
69
90
  console.log(`Data received for ${data.dataRef || 'undefined'}: ${util.inspect(data.value, { depth: null })}`);
70
91
  }
@@ -86,8 +107,18 @@ const client = new MmsClient((event, data) => {
86
107
  console.log(`Reporting enabled for ${data.rcbRef}`);
87
108
  } else if (data.event === 'reportingDisabled') {
88
109
  console.log(`Reporting disabled for ${data.rcbRef}`);
110
+ } else if (data.event === 'dataSetCreated') {
111
+ console.log(`DataSet created: ${data.datasetRef}`);
112
+ } else if (data.event === 'dataSetDeleted') {
113
+ console.log(`DataSet deleted: ${data.datasetRef}`);
114
+ } else if (data.event === 'stateChanged') {
115
+ console.log(`Connection state changed: ${data.state}, isConnected: ${data.isConnected}`);
89
116
  }
90
117
  }
118
+
119
+ if (event === 'conn' && data.event === 'stateChanged') {
120
+ console.log(`Connection state changed: ${data.state}, isConnected: ${data.isConnected}`);
121
+ }
91
122
  });
92
123
 
93
124
  async function main() {
@@ -102,12 +133,12 @@ async function main() {
102
133
  reconnectDelay: 2
103
134
  });
104
135
  await sleep(5000);
105
- // Выполнение операции управления
106
- //console.log('And now we try do control operation!!!!!!!!!!!!!!!...');
107
- //client.controlObject("WAGO61850ServerDevice/XCBR1.Pos", true);
136
+
137
+ // console.log('And now we try do control operation!!!!!!!!!!!!!!!...');
138
+ // client.controlObject("WAGO61850ServerDevice/XCBR1.Pos", true);
108
139
 
109
140
  // Дополнительное ожидание для обработки операции управления
110
- //await sleep(5000);
141
+ // await sleep(5000);
111
142
 
112
143
  // Ожидание обработки данных и отчетов
113
144
  console.log('Waiting for data and reports...');
@@ -116,7 +147,7 @@ async function main() {
116
147
  // Отключение отчетов
117
148
  const rcbRef = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0101';
118
149
  console.log(`Disabling reporting for ${rcbRef}`);
119
- client.disableReporting(rcbRef);
150
+ client.disableReporting(rcbRef);
120
151
 
121
152
  console.log('Client status:', client.getStatus());
122
153
 
@@ -129,4 +160,178 @@ async function main() {
129
160
  }
130
161
  }
131
162
 
163
+ main().catch(err => console.error('Fatal error:', err.message));*/
164
+
165
+ const { MmsClient } = require('../build/Release/addon_iec61850');
166
+ const util = require('util');
167
+
168
+ const client = new MmsClient((event, data) => {
169
+ console.log(`Event: ${event}, Data: ${util.inspect(data, { depth: null })}`);
170
+
171
+ if (event === 'conn' && data.event === 'opened') {
172
+ console.log('Connection opened, browsing data model...');
173
+ // Запускаем асинхронную логику после открытия соединения
174
+ handleConnectionOpened();
175
+ }
176
+
177
+ if (event === 'data' && data.type === 'data') {
178
+ if (data.event === 'logicalDevices') {
179
+ console.log(`Logical Devices received: ${util.inspect(data.logicalDevices, { depth: null })}`);
180
+ } else if (data.event === 'dataSetDirectory') {
181
+ console.log(`DataSet Directory for ${data.logicalNodeRef}: ${util.inspect(data.dataSets, { depth: null })}`);
182
+ } else if (data.event === 'dataModel') {
183
+ console.log(`Data Model received: ${util.inspect(data.dataModel, { depth: null })}`);
184
+ } else if (data.event === 'dataSet') {
185
+ console.log(`DataSet received for ${data.datasetRef}: ${util.inspect(data.value, { depth: null })}`);
186
+ } else if (data.event === 'multipleDataSets') {
187
+ console.log(`Multiple DataSets received for ${util.inspect(data.datasetRefs, { depth: null })}:`);
188
+ data.values.forEach((value, index) => {
189
+ if (value.isValid !== false) {
190
+ console.log(` DataSet[${index}]: ${data.datasetRefs[index]}, Value: ${util.inspect(value, { depth: null })}`);
191
+ } else {
192
+ console.log(` DataSet[${index}]: ${data.datasetRefs[index]}, Error: ${value.errorReason}`);
193
+ }
194
+ });
195
+ } else if (data.event === 'report') {
196
+ console.log(`Report received for ${data.rcbRef} (rptId: ${data.rptId}):`);
197
+ if (data.timestamp) {
198
+ console.log(` Timestamp: ${data.timestamp}`);
199
+ }
200
+ data.values.forEach((value, index) => {
201
+ if (data.reasonsForInclusion[index] !== 0) {
202
+ console.log(` Value[${index}]: ${util.inspect(value, { depth: null })}, Reason: ${data.reasonsForInclusion[index]}`);
203
+ }
204
+ });
205
+ } else if (data.event === 'batchData') {
206
+ console.log(`Batch Data received for ${util.inspect(data.dataRefs, { depth: null })}:`);
207
+ data.values.forEach((result, index) => {
208
+ if (result.isValid) {
209
+ console.log(` dataRef[${index}]: ${data.dataRefs[index]}, Value: ${util.inspect(result.value, { depth: null })}`);
210
+ } else {
211
+ console.log(` dataRef[${index}]: ${data.dataRefs[index]}, Error: ${result.errorReason}`);
212
+ }
213
+ });
214
+ } else {
215
+ console.log(`Data received for ${data.dataRef || 'undefined'}: ${util.inspect(data.value, { depth: null })}`);
216
+ }
217
+ }
218
+
219
+ if (event === 'data' && data.type === 'error') {
220
+ console.error(`Error received: ${data.reason}`);
221
+ }
222
+
223
+ if (event === 'conn' && data.event === 'reconnecting') {
224
+ console.error(`Reconnection failed: ${data.reason}`);
225
+ if (data.reason.includes('attempt 3')) {
226
+ throw new Error('Max reconnection attempts reached');
227
+ }
228
+ }
229
+
230
+ if (event === 'data' && data.type === 'control') {
231
+ if (data.event === 'reportingEnabled') {
232
+ console.log(`Reporting enabled for ${data.rcbRef}`);
233
+ } else if (data.event === 'reportingDisabled') {
234
+ console.log(`Reporting disabled for ${data.rcbRef}`);
235
+ } else if (data.event === 'dataSetCreated') {
236
+ console.log(`DataSet created: ${data.datasetRef}`);
237
+ } else if (data.event === 'dataSetDeleted') {
238
+ console.log(`DataSet deleted: ${data.datasetRef}`);
239
+ } else if (data.event === 'stateChanged') {
240
+ console.log(`Connection state changed: ${data.state}, isConnected: ${data.isConnected}`);
241
+ }
242
+ }
243
+
244
+ if (event === 'conn' && data.event === 'stateChanged') {
245
+ console.log(`Connection state changed: ${data.state}, isConnected: ${data.isConnected}`);
246
+ }
247
+ });
248
+
249
+ // Вспомогательная функция сна
250
+ const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
251
+
252
+ // Основная асинхронная функция обработки после открытия соединения
253
+ async function handleConnectionOpened() {
254
+ try {
255
+ // Просмотр модели данных
256
+ const dataModel = await client.browseDataModel();
257
+ console.log('Data Model:', util.inspect(dataModel, { depth: null }));
258
+
259
+ // Извлечение всех датасетов
260
+ const dataSets = [];
261
+ dataModel.forEach(ld => {
262
+ ld.logicalNodes.forEach(ln => {
263
+ ln.dataSets.forEach(ds => {
264
+ console.log(`Found dataset: ${ds.reference}`);
265
+ dataSets.push(ds);
266
+ });
267
+ });
268
+ });
269
+
270
+ // Пакетное чтение датасетов
271
+ if (dataSets.length > 0) {
272
+ console.log('Reading datasets in batch...');
273
+ const dataSetRefs = dataSets.map(ds => ds.reference);
274
+ await client.readDataSetValues(dataSetRefs);
275
+ }
276
+
277
+ // Пакетное чтение отдельных значений
278
+ console.log('Reading data...');
279
+ const dataRefs = [
280
+ 'WAGO61850ServerDevice/XCBR1.Pos.stVal',
281
+ 'WAGO61850ServerDevice/GGIO1.Ind.stVal',
282
+ 'WAGO61850ServerDevice/CALH1.GrAlm.stVal'
283
+ ];
284
+ await client.readData(dataRefs);
285
+
286
+ // Включение отчётности
287
+ const rcbRef = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0101';
288
+ const dataSetRef = 'WAGO61850ServerDevice/LLN0.DataSet01';
289
+ console.log(`Enabling reporting for ${rcbRef} with dataset ${dataSetRef}`);
290
+ await client.enableReporting(rcbRef, dataSetRef);
291
+
292
+ } catch (err) {
293
+ console.error('Error in handleConnectionOpened:', err.message);
294
+ }
295
+ }
296
+
297
+ // Главная функция
298
+ async function main() {
299
+ try {
300
+ console.log('Starting client...');
301
+ await client.connect({
302
+ ip: '192.168.0.102',
303
+ port: 102,
304
+ clientID: 'mms_client1',
305
+ reconnectDelay: 2
306
+ });
307
+
308
+ // Ждём открытия соединения (событие будет обработано в колбэке)
309
+ await sleep(5000);
310
+
311
+ // Опционально: управление (раскомментируй при необходимости)
312
+ // console.log('Performing control operation...');
313
+ // await client.controlObject("WAGO61850ServerDevice/XCBR1.Pos", true);
314
+ // await sleep(5000);
315
+
316
+ // Ожидание данных и отчётов
317
+ console.log('Waiting for data and reports...');
318
+ await sleep(30000);
319
+
320
+ // Отключение отчётов
321
+ const rcbRef = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0101';
322
+ console.log(`Disabling reporting for ${rcbRef}`);
323
+ await client.disableReporting(rcbRef);
324
+
325
+ console.log('Client status:', client.getStatus());
326
+ console.log('Closing client...');
327
+ await client.close();
328
+ console.log('Client closed.');
329
+
330
+ } catch (err) {
331
+ console.error('Main error:', err.message);
332
+ await client.close().catch(e => console.error('Close error:', e.message));
333
+ }
334
+ }
335
+
336
+ // Запуск
132
337
  main().catch(err => console.error('Fatal error:', err.message));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amigo9090/ih-libiec61850-node",
3
- "version": "1.0.26",
3
+ "version": "1.0.28",
4
4
  "description": "Node.js addon for IEC 61850 client (MMS, GOOSE) using libiec61850",
5
5
  "main": "index.js",
6
6
  "keywords": [