@amigo9090/ih-libiec61850-node 1.0.41 → 1.0.43

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.
@@ -4,11 +4,32 @@ const util = require('util');
4
4
  const client = new MmsClient((event, data) => {
5
5
  console.log(`Event: ${event}, Data: ${util.inspect(data, { depth: null })}`);
6
6
 
7
- if (event === 'conn' && data.event === 'opened') {
7
+ /*if (event === 'conn' && data.event === 'opened') {
8
8
  console.log('Connection opened, browsing data model...');
9
- handleConnectionOpened();
9
+ //handleConnectionOpened();
10
+ handleConnectionOpened2();
11
+ }*/
12
+
13
+ if (event === 'conn' && data.event === 'opened') {
14
+ console.log('Connection opened');
15
+ // Теперь пользователь сам решит, как исследовать модель
16
+ console.log('\n=== Примеры использования: ===');
17
+ console.log('1. Получить корневые узлы:');
18
+ console.log(' client.browseDataModel()');
19
+ console.log('\n2. Получить DataObjects конкретного узла:');
20
+ console.log(' client.browseDataModel("WAGO61850ServerDevice/LLN0")');
21
+ console.log('\n3. Получить атрибуты DataObject:');
22
+ console.log(' client.browseDataModel("WAGO61850ServerDevice/XCBR1.Pos")');
23
+ console.log('\n4. Получить члены DataSet:');
24
+ console.log(' client.browseDataModel("WAGO61850ServerDevice/LLN0.DataSet01")');
25
+ console.log('\n5. Получить информацию об отчете:');
26
+ console.log(' client.browseDataModel("WAGO61850ServerDevice/LLN0.RP$ReportBlock0101")');
27
+
28
+ // Автоматически получаем корневые узлы для примера
29
+ exploreModel();
10
30
  }
11
31
 
32
+
12
33
  if (event === 'data' && data.type === 'data') {
13
34
  if (data.event === 'logicalDevices') {
14
35
  console.log(`Logical Devices received: ${util.inspect(data.logicalDevices, { depth: null })}`);
@@ -85,7 +106,7 @@ const client = new MmsClient((event, data) => {
85
106
 
86
107
  const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
87
108
 
88
- async function handleConnectionOpened() {
109
+ /*async function handleConnectionOpened() {
89
110
  try {
90
111
  const dataModel = await client.browseDataModel();
91
112
  console.log('Data Model:', util.inspect(dataModel, { depth: null }));
@@ -118,7 +139,7 @@ async function handleConnectionOpened() {
118
139
  console.log(` Значений: ${res.count}, Удаляемые: ${res.isDeletable}`);
119
140
 
120
141
  // Функция для рекурсивного вывода вложенных структур
121
- const printValue = (value, indent = ' ') => {
142
+ /*const printValue = (value, indent = ' ') => {
122
143
  if (value && typeof value === 'object' && !Array.isArray(value)) {
123
144
  Object.entries(value).forEach(([key, val]) => {
124
145
  if (val && typeof val === 'object' && !Array.isArray(val)) {
@@ -145,9 +166,50 @@ async function handleConnectionOpened() {
145
166
  console.log(` ${ref}:`);
146
167
  printValue(value, ' ');
147
168
  });
148
- });
169
+
149
170
 
150
- /*console.log('Reading data...');
171
+ // Функция для рекурсивного вывода с полным отображением всех элементов
172
+ const printModel = (model, indent = '') => {
173
+ if (Array.isArray(model)) {
174
+ model.forEach((item, index) => {
175
+ console.log(`${indent}[${index}]:`);
176
+ printModel(item, indent + ' ');
177
+ });
178
+ } else if (model && typeof model === 'object') {
179
+ Object.entries(model).forEach(([key, value]) => {
180
+ if (key === 'dataObjects' && Array.isArray(value)) {
181
+ console.log(`${indent}${key}: [`);
182
+ value.forEach((doObj, idx) => {
183
+ console.log(`${indent} [${idx}]:`);
184
+ printModel(doObj, indent + ' ');
185
+ });
186
+ console.log(`${indent}]`);
187
+ } else if (key === 'attributes' && typeof value === 'object') {
188
+ console.log(`${indent}${key}: {`);
189
+ printModel(value, indent + ' ');
190
+ console.log(`${indent}}`);
191
+ } else if (Array.isArray(value)) {
192
+ console.log(`${indent}${key}: [`);
193
+ value.forEach((item, idx) => {
194
+ console.log(`${indent} [${idx}]: ${item}`);
195
+ });
196
+ console.log(`${indent}]`);
197
+ } else if (typeof value === 'object') {
198
+ console.log(`${indent}${key}: {`);
199
+ printModel(value, indent + ' ');
200
+ console.log(`${indent}}`);
201
+ } else {
202
+ console.log(`${indent}${key}: ${value}`);
203
+ }
204
+ });
205
+ } else {
206
+ console.log(`${indent}${model}`);
207
+ }
208
+ };
209
+
210
+ });
211
+
212
+ console.log('Reading data...');
151
213
  const dataRefs = [
152
214
  'WAGO61850ServerDevice/XCBR1.Pos[ST]',
153
215
  'WAGO61850ServerDevice/GGIO1.Ind1.stVal',
@@ -159,23 +221,23 @@ async function handleConnectionOpened() {
159
221
  const rcbRef2 = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0201';
160
222
  const dataSetRef2 = 'WAGO61850ServerDevice/LLN0.DataSet02';
161
223
  console.log(`Enabling reporting for ${rcbRef2} with dataset ${dataSetRef2}`);
162
- await client.enableReporting(rcbRef2, dataSetRef2);*/
224
+ await client.enableReporting(rcbRef2, dataSetRef2);
163
225
 
164
- console.log('Reading data...');
226
+ /*console.log('Reading data...');
165
227
  const dataRefs = [
166
228
  'A01LD0/Q1_XCBR1.Pos[ST]',
167
229
  'A01LD0/In_GGIO1.Ind1',
168
230
  'A01LD0/CALH1.GrAlm.stVal'
169
231
  ];
170
232
  const readRefResult = await client.readData(dataRefs);
171
- console.log("readRefResult " + util.inspect(readRefResult, { depth: null }));
233
+ console.log("readRefResult " + util.inspect(readRefResult, { depth: null }));*/
172
234
 
173
235
  /* const rcbRef = 'A01LD0/LLN0.RP.repTI1';
174
236
  const dataSetRef = 'A01LD0/LLN0.TI_ASU';
175
237
  console.log(`Enabling reporting for ${rcbRef} with dataset ${dataSetRef}`);
176
238
  await client.enableReporting(rcbRef, dataSetRef);*/
177
239
 
178
- const rcbRef2 = 'A01LD0/LLN0.BR.repTS1';
240
+ /*const rcbRef2 = 'A01LD0/LLN0.BR.repTS1';
179
241
  const dataSetRef2 = 'A01LD0/LLN0.TS_ASU';
180
242
  console.log(`Enabling reporting for ${rcbRef2} with dataset ${dataSetRef2}`);
181
243
  await client.enableReporting(rcbRef2, dataSetRef2);
@@ -183,13 +245,470 @@ async function handleConnectionOpened() {
183
245
  } catch (err) {
184
246
  console.error('Error in handleConnectionOpened:', err.message);
185
247
  }
248
+ }*/
249
+
250
+ async function handleConnectionOpened() {
251
+ try {
252
+ const dataModel = await client.browseDataModel();
253
+
254
+ const dataSets = [];
255
+ const reports = [];
256
+
257
+ dataModel.forEach(ld => {
258
+ console.log(`\nLogical Device: ${ld.name}`);
259
+
260
+ ld.logicalNodes.forEach(ln => {
261
+ console.log(` Logical Node: ${ln.name} (${ln.reference})`);
262
+
263
+ // Вывод DataSets
264
+ if (ln.dataSets && ln.dataSets.length > 0) {
265
+ console.log(` Datasets (${ln.dataSets.length}):`);
266
+ ln.dataSets.forEach(ds => {
267
+ console.log(` - ${ds.reference} (Deletable: ${ds.isDeletable})`);
268
+ dataSets.push(ds);
269
+ });
270
+ }
271
+
272
+ // Вывод отчетов (Report Control Blocks)
273
+ if (ln.reports && ln.reports.length > 0) {
274
+ console.log(` Reports (${ln.reports.length}):`);
275
+ ln.reports.forEach((report, index) => {
276
+ console.log(` [${index + 1}] ${report.reference}`);
277
+ console.log(` Type: ${report.type} (${report.description || 'N/A'})`);
278
+ if (report.datasetRef) {
279
+ console.log(` Dataset: ${report.datasetRef}`);
280
+ }
281
+ if (report.reportId) {
282
+ console.log(` Report ID: ${report.reportId}`);
283
+ }
284
+ console.log(` Enabled: ${report.enabled !== undefined ? report.enabled : 'Unknown'}`);
285
+ reports.push(report);
286
+ });
287
+ } else {
288
+ console.log(` No reports found`);
289
+ }
290
+ });
291
+ });
292
+
293
+ console.log('\n=== SUMMARY ===');
294
+ console.log(`Total Logical Devices: ${dataModel.length}`);
295
+
296
+ let totalDataSets = 0;
297
+ let totalReports = 0;
298
+
299
+ dataModel.forEach(ld => {
300
+ ld.logicalNodes.forEach(ln => {
301
+ totalDataSets += (ln.dataSets ? ln.dataSets.length : 0);
302
+ totalReports += (ln.reports ? ln.reports.length : 0);
303
+ });
304
+ });
305
+
306
+ console.log(`Total Datasets found: ${totalDataSets}`);
307
+ console.log(`Total Reports found: ${totalReports}`);
308
+
309
+ // Выводим все найденные отчеты для удобства
310
+ console.log('\n=== ALL FOUND REPORTS ===');
311
+ reports.forEach((report, index) => {
312
+ const enabledStatus = report.enabled !== undefined ?
313
+ (report.enabled ? 'ENABLED' : 'DISABLED') : 'UNKNOWN';
314
+ console.log(`${index + 1}. ${report.reference} (${report.type}) - ${enabledStatus}`);
315
+ if (report.datasetRef) {
316
+ console.log(` Dataset: ${report.datasetRef}`);
317
+ }
318
+ });
319
+
320
+ console.log('\n=== RECOMMENDED REPORTS FOR ENABLING ===');
321
+ // Ищем отчеты с DataSet02 (как в примере)
322
+ const recommendedReports = reports.filter(r =>
323
+ r.datasetRef && r.datasetRef.includes('DataSet02')
324
+ );
325
+
326
+ if (recommendedReports.length > 0) {
327
+ recommendedReports.forEach((report, index) => {
328
+ console.log(`${index + 1}. ${report.reference}`);
329
+ console.log(` Dataset: ${report.datasetRef}`);
330
+ console.log(` To enable: client.enableReporting("${report.reference}", "${report.datasetRef}")`);
331
+ });
332
+ } else {
333
+ console.log('No reports with DataSet02 found.');
334
+ // Предлагаем другие отчеты
335
+ if (reports.length > 0) {
336
+ console.log('\nAvailable reports with datasets:');
337
+ reports.filter(r => r.datasetRef).forEach((report, index) => {
338
+ console.log(`${index + 1}. ${report.reference} -> ${report.datasetRef}`);
339
+ });
340
+ }
341
+ }
342
+ } catch (err) {
343
+ console.error('Error in handleConnectionOpened:', err.message);
344
+ }
345
+ }
346
+
347
+ async function handleConnectionOpened2() {
348
+ try {
349
+ const dataModel = await client.browseDataModel();
350
+ console.log('Data Model:', util.inspect(dataModel, { depth: null }));
351
+
352
+ const dataSets = [];
353
+ const reports = [];
354
+
355
+ dataModel.forEach(ld => {
356
+ console.log(`\nLogical Device: ${ld.name}`);
357
+
358
+ ld.logicalNodes.forEach(ln => {
359
+ console.log(` Logical Node: ${ln.name}`);
360
+
361
+ // Вывод DataSets
362
+ if (ln.dataSets && ln.dataSets.length > 0) {
363
+ ln.dataSets.forEach(ds => {
364
+ console.log(` Dataset: ${ds.reference} (Deletable: ${ds.isDeletable})`);
365
+ dataSets.push(ds);
366
+ });
367
+ }
368
+
369
+ // Вывод отчетов (RCB - Report Control Blocks)
370
+ if (ln.reports && ln.reports.length > 0) {
371
+ console.log(` Reports (${ln.reports.length}):`);
372
+ ln.reports.forEach((report, index) => {
373
+ console.log(` [${index + 1}] ${report.reference}`);
374
+ console.log(` Type: ${report.type} (${report.description})`);
375
+ if (report.datasetRef) {
376
+ console.log(` Dataset: ${report.datasetRef}`);
377
+ }
378
+ if (report.reportId) {
379
+ console.log(` Report ID: ${report.reportId}`);
380
+ }
381
+ console.log(` Enabled: ${report.enabled}`);
382
+ reports.push(report);
383
+ });
384
+ } else {
385
+ console.log(` No reports found for ${ln.reference}`);
386
+ }
387
+ });
388
+ });
389
+
390
+ console.log('\n=== SUMMARY ===');
391
+ console.log(`Total Logical Devices: ${dataModel.length}`);
392
+ console.log(`Total Datasets found: ${dataSets.length}`);
393
+ console.log(`Total Reports found: ${reports.length}`);
394
+
395
+ // Выводим все найденные отчеты для удобства
396
+ console.log('\n=== ALL FOUND REPORTS ===');
397
+ reports.forEach((report, index) => {
398
+ console.log(`${index + 1}. ${report.reference} (${report.type})`);
399
+ });
400
+
401
+ // 1. Читаем модель устройства
402
+ /*const dataModel = await client.browseDataModel();
403
+ console.log('Data Model:', util.inspect(dataModel, { depth: null }));
404
+
405
+ const dataSets = [];
406
+ dataModel.forEach(ld => {
407
+ ld.logicalNodes.forEach(ln => {
408
+ ln.dataSets.forEach(ds => {
409
+ console.log(`Found dataset: ${ds.reference}`);
410
+ dataSets.push(ds);
411
+ });
412
+ });
413
+ });*/
414
+
415
+ // 2. Читаем одиночные значения
416
+ console.log('Reading single values...');
417
+ const dataRefs = [
418
+ 'WAGO61850ServerDevice/XCBR1.Pos[ST]',
419
+ 'WAGO61850ServerDevice/GGIO1.Ind1[ST]',
420
+ 'WAGO61850ServerDevice/CALH12.GrAlm.stVal'
421
+ ];
422
+ const readRefResult = await client.readData(dataRefs);
423
+ console.log("readRefResult " + util.inspect(readRefResult, { depth: null }));
424
+
425
+ // 3. Читаем и кэшируем структуры (делаем это один раз)
426
+ console.log('First read (with caching)...');
427
+ const firstRead = await client.readDataSetModel([
428
+ 'WAGO61850ServerDevice/LLN0.DataSet01',
429
+ 'WAGO61850ServerDevice/LLN0.DataSet02',
430
+ 'WAGO61850ServerDevice/LLN0.DataSet03'
431
+ ]);
432
+
433
+ console.log('First read completed, structures cached');
434
+
435
+ // 4. Теперь можем использовать быстрый polling значений Dataset
436
+ console.log('\nStarting fast polling...');
437
+
438
+ for (let i = 0; i < 10; i++) {
439
+ console.log(`\n--- Poll ${i+1} ---`);
440
+
441
+ const startTime = Date.now();
442
+
443
+ const pollResults = await client.pollDataSetValues(['WAGO61850ServerDevice/LLN0.DataSet02']); // Быстрое чтение значений DataSet
444
+
445
+ const endTime = Date.now();
446
+
447
+ pollResults.forEach((result, idx) => {
448
+ if (result.isValid) {
449
+ console.log(`DataSet ${result.datasetRef}: ${result.count} values`);
450
+ console.log(` Read time: ${result.readTimeMicros} µs`);
451
+ console.log(` Process time: ${result.processTimeMicros} µs`);
452
+
453
+ // Выводим значения
454
+ Object.entries(result.values).forEach(([ref, value]) => {
455
+ console.log(` ${ref}:`, util.inspect(value, { depth: null }));
456
+ });
457
+ } else {
458
+ console.error(`Error: ${result.errorReason}`);
459
+ }
460
+ });
461
+
462
+ console.log(`Total poll time: ${endTime - startTime} ms`);
463
+
464
+ // Ждем перед следующим опросом
465
+ await sleep(1000);
466
+ }
467
+
468
+ } catch (err) {
469
+ console.error('Error in handleConnectionOpened2:', err.message);
470
+ }
471
+ }
472
+
473
+ /*async function exploreModel() {
474
+ try {
475
+ console.log('\n=== 1. Получение корневых узлов ===');
476
+ const rootNodes = await client.browseDataModel();
477
+
478
+ console.log('\nНайдено Logical Nodes:');
479
+ rootNodes.forEach((ln, index) => {
480
+ console.log(`\n${index + 1}. ${ln.name} (${ln.reference})`);
481
+
482
+ // Выводим ВСЕ датасеты
483
+ if (ln.dataSets && ln.dataSets.length > 0) {
484
+ console.log(` Datasets (${ln.dataSets.length}):`);
485
+ ln.dataSets.forEach((ds, idx) => {
486
+ console.log(` ${idx + 1}. ${ds.name}: ${ds.reference}`);
487
+ });
488
+ } else {
489
+ console.log(` Datasets: 0`);
490
+ }
491
+
492
+ // Выводим ВСЕ отчеты
493
+ if (ln.reports && ln.reports.length > 0) {
494
+ console.log(` Reports (${ln.reports.length}):`);
495
+ ln.reports.forEach((report, idx) => {
496
+ const typeDesc = report.type === 'RP' ? 'Unbuffered' : 'Buffered';
497
+ console.log(` ${idx + 1}. ${report.name} (${report.type} - ${typeDesc}): ${report.reference}`);
498
+ });
499
+ } else {
500
+ console.log(` Reports: 0`);
501
+ }
502
+ });
503
+
504
+ // Выбираем LLN0 для дальнейшего исследования
505
+ const lln0 = rootNodes.find(ln => ln.name === 'LLN0');
506
+ if (lln0) {
507
+ console.log('\n=== 2. Исследуем LLN0 ===');
508
+ const lln0Details = await client.browseDataModel(lln0.reference);
509
+
510
+ console.log(`\nDataObjects в ${lln0Details.reference}: ${llln0Details.dataObjectsCount}`);
511
+ console.log(`DataSets в ${lln0Details.reference}: ${llln0Details.dataSetsCount}`);
512
+
513
+ // Показываем ВСЕ DataObjects
514
+ console.log('\nВсе DataObjects:');
515
+ lln0Details.dataObjects.forEach((doObj, index) => {
516
+ console.log(`${index + 1}. ${doObj.name} (${doObj.cdc || 'Unknown'}) - ${doObj.reference}`);
517
+ });
518
+
519
+ // Выбираем первый DataSet для кэширования
520
+ if (lln0Details.dataSets.length > 0) {
521
+ const firstDataSet = lln0Details.dataSets[0];
522
+ console.log(`\n=== 3. Кэшируем DataSet ${firstDataSet.reference} ===`);
523
+ const dsDetails = await client.browseDataModel(firstDataSet.reference);
524
+
525
+ console.log(`DataSet ${dsDetails.reference}:`);
526
+ console.log(` Удаляемый: ${dsDetails.isDeletable}`);
527
+ console.log(` Членов: ${dsDetails.memberCount}`);
528
+ console.log('\n Первые члены:');
529
+ dsDetails.members.slice(0, 5).forEach((member, index) => {
530
+ console.log(` ${index + 1}. ${member.reference}`);
531
+ });
532
+
533
+ // Теперь можем быстро читать этот DataSet
534
+ console.log('\n=== 4. Быстрое чтение DataSet ===');
535
+ const pollResults = await client.pollDataSetValues([firstDataSet.reference]);
536
+ console.log('Poll results:', util.inspect(pollResults, { depth: 2 }));
537
+ }
538
+
539
+ // Выбираем первый отчет для кэширования
540
+ if (lln0.reports.length > 0) {
541
+ const firstReport = lln0.reports.find(r => r.reference.includes('ReportBlock0101'));
542
+ if (firstReport) {
543
+ console.log(`\n=== 5. Кэшируем отчет ${firstReport.reference} ===`);
544
+ const reportDetails = await client.browseDataModel(firstReport.reference);
545
+
546
+ console.log(`Отчет ${reportDetails.reference}:`);
547
+ console.log(` Тип: ${reportDetails.reportType}`);
548
+ console.log(` DataSet: ${reportDetails.datasetRef}`);
549
+ console.log(` Включен: ${reportDetails.enabled}`);
550
+ console.log(` Report ID: ${reportDetails.reportId}`);
551
+
552
+ // Подписываемся на отчет
553
+ console.log(`\n=== 6. Подписываемся на отчет ===`);
554
+ await client.enableReporting(firstReport.reference, reportDetails.datasetRef);
555
+ }
556
+ }
557
+ }
558
+
559
+ // Пример чтения одиночного значения
560
+ console.log('\n=== 7. Чтение одиночных значений ===');
561
+ const singleValues = await client.readData([
562
+ 'WAGO61850ServerDevice/XCBR1.Pos[ST]',
563
+ 'WAGO61850ServerDevice/GGIO1.Ind1[ST]'
564
+ ]);
565
+ console.log('Single values:', util.inspect(singleValues, { depth: 2 }));
566
+
567
+ } catch (err) {
568
+ console.error('Error in exploreModel:', err.message);
569
+ }
570
+ }*/
571
+
572
+ async function exploreModel() {
573
+ try {
574
+ console.log('\n=== 1. Получение корневых узлов ===');
575
+ const rootNodes = await client.browseDataModel();
576
+
577
+ console.log('\nНайдено Logical Nodes:');
578
+ rootNodes.forEach((ln, index) => {
579
+ console.log(`\n${index + 1}. ${ln.name} (${ln.reference})`);
580
+
581
+ // Выводим ВСЕ датасеты
582
+ if (ln.dataSets && ln.dataSets.length > 0) {
583
+ console.log(` Datasets (${ln.dataSets.length}):`);
584
+ ln.dataSets.forEach((ds, idx) => {
585
+ console.log(` ${idx + 1}. ${ds.name}: ${ds.reference}`);
586
+ });
587
+ } else {
588
+ console.log(` Datasets: 0`);
589
+ }
590
+
591
+ // Выводим ВСЕ отчеты
592
+ if (ln.reports && ln.reports.length > 0) {
593
+ console.log(` Reports (${ln.reports.length}):`);
594
+ ln.reports.forEach((report, idx) => {
595
+ const typeDesc = report.type === 'RP' ? 'Unbuffered' : 'Buffered';
596
+ console.log(` ${idx + 1}. ${report.name} (${report.type} - ${typeDesc}): ${report.reference}`);
597
+ });
598
+ } else {
599
+ console.log(` Reports: 0`);
600
+ }
601
+ });
602
+
603
+ // Выбираем LLN0 для дальнейшего исследования
604
+ const lln0 = rootNodes.find(ln => ln.name === 'LLN0');
605
+ if (lln0) {
606
+ console.log('\n=== 2. Исследуем LLN0 ===');
607
+ const lln0Details = await client.browseDataModel(lln0.reference);
608
+
609
+ console.log(`\nDataObjects в ${lln0Details.reference}: ${lln0Details.dataObjectsCount}`);
610
+ console.log(`DataSets в ${lln0Details.reference}: ${lln0Details.dataSetsCount}`);
611
+
612
+ // Показываем ВСЕ DataObjects
613
+ console.log('\nВсе DataObjects:');
614
+ lln0Details.dataObjects.forEach((doObj, index) => {
615
+ console.log(`${index + 1}. ${doObj.name} (${doObj.cdc || 'Unknown'}) - ${doObj.reference}`);
616
+ });
617
+
618
+ // Выбираем первый DataSet для кэширования
619
+ if (lln0Details.dataSets.length > 0) {
620
+ const firstDataSet = lln0Details.dataSets[0];
621
+ console.log(`\n=== 3. Кэшируем DataSet ${firstDataSet.reference} ===`);
622
+ const dsDetails = await client.browseDataModel(firstDataSet.reference);
623
+
624
+ console.log(`\nDataSet ${dsDetails.reference}:`);
625
+ console.log(` Удаляемый: ${dsDetails.isDeletable}`);
626
+ console.log(` Членов: ${dsDetails.memberCount}`);
627
+ console.log('\n Все члены:');
628
+ dsDetails.members.forEach((member, index) => {
629
+ console.log(` ${index + 1}. ${member.reference}`);
630
+ });
631
+
632
+ // Теперь можем быстро читать этот DataSet
633
+ console.log('\n=== 4. Быстрое чтение DataSet ===');
634
+ const pollResults = await client.pollDataSetValues([firstDataSet.reference]);
635
+
636
+ console.log('\nPoll results:');
637
+ pollResults.forEach((result, idx) => {
638
+ if (result.isValid) {
639
+ console.log(`\nDataSet ${result.datasetRef}: ${result.count} значений`);
640
+ console.log(` Read time: ${result.readTimeMicros} µs`);
641
+ console.log(` Process time: ${result.processTimeMicros} µs`);
642
+
643
+ // Выводим ВСЕ значения
644
+ console.log('\n Значения:');
645
+ Object.entries(result.values).forEach(([ref, value], index) => {
646
+ console.log(` [${index + 1}] ${ref}:`, util.inspect(value, {
647
+ depth: null,
648
+ colors: true,
649
+ maxArrayLength: 10
650
+ }));
651
+ });
652
+ } else {
653
+ console.error(` Error: ${result.errorReason}`);
654
+ }
655
+ });
656
+ }
657
+
658
+ // Выбираем первый отчет для кэширования
659
+ if (lln0.reports.length > 0) {
660
+ const firstReport = lln0.reports.find(r => r.reference.includes('ReportBlock0101'));
661
+ if (firstReport) {
662
+ console.log(`\n=== 5. Кэшируем отчет ${firstReport.reference} ===`);
663
+ const reportDetails = await client.browseDataModel(firstReport.reference);
664
+
665
+ console.log(`\nОтчет ${reportDetails.reference}:`);
666
+ console.log(` Тип: ${reportDetails.reportType}`);
667
+ console.log(` DataSet: ${reportDetails.datasetRef}`);
668
+ console.log(` Включен: ${reportDetails.enabled}`);
669
+ console.log(` Report ID: ${reportDetails.reportId || 'N/A'}`);
670
+ console.log(` Triggers: ${reportDetails.trgOps}`);
671
+ console.log(` Integrity Period: ${reportDetails.intgPd} ms`);
672
+ console.log(` Buffer Time: ${reportDetails.bufTm} ms`);
673
+ console.log(` GI: ${reportDetails.gi}`);
674
+
675
+ // Подписываемся на отчет
676
+ console.log(`\n=== 6. Подписываемся на отчет ===`);
677
+ await client.enableReporting(firstReport.reference, reportDetails.datasetRef);
678
+ }
679
+ }
680
+ }
681
+
682
+ // Пример чтения одиночного значения
683
+ console.log('\n=== 7. Чтение одиночных значений ===');
684
+ const singleValues = await client.readData([
685
+ 'WAGO61850ServerDevice/XCBR1.Pos[ST]',
686
+ 'WAGO61850ServerDevice/GGIO1.Ind1[ST]'
687
+ ]);
688
+
689
+ console.log('\nSingle values:');
690
+ singleValues.forEach((result, index) => {
691
+ if (result.isValid) {
692
+ console.log(`[${index + 1}] ${result.dataRef}:`, util.inspect(result.value, {
693
+ depth: null,
694
+ colors: true
695
+ }));
696
+ } else {
697
+ console.log(`[${index + 1}] ${result.dataRef}: ERROR - ${result.errorReason}`);
698
+ }
699
+ });
700
+
701
+ } catch (err) {
702
+ console.error('Error in exploreModel:', err.message);
703
+ console.error(err.stack);
704
+ }
186
705
  }
187
706
 
188
707
  async function main() {
189
708
  try {
190
709
  console.log('Starting client...');
191
710
  await client.connect({
192
- ip: '192.168.0.122',
711
+ ip: '192.168.0.106',
193
712
  port: 102,
194
713
  clientID: 'mms_client1',
195
714
  reconnectDelay: 2,
@@ -201,13 +720,13 @@ async function main() {
201
720
  console.log('Waiting for data and reports...');
202
721
  await sleep(30000);
203
722
 
204
- const rcbRef = 'A01LD0/LLN0.BR.repTS1';
723
+ /*const rcbRef = 'A01LD0/LLN0.BR.repTS1';
205
724
  console.log(`Disabling reporting for ${rcbRef}`);
206
- await client.disableReporting(rcbRef);
725
+ await client.disableReporting(rcbRef);*/
207
726
 
208
- /*const rcbRef2 = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0201';
727
+ const rcbRef2 = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0101';
209
728
  console.log(`Disabling reporting for ${rcbRef2}`);
210
- await client.disableReporting(rcbRef2);*/
729
+ await client.disableReporting(rcbRef2);
211
730
 
212
731
  console.log('Client status:', client.getStatus());
213
732
  console.log('Closing client...');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amigo9090/ih-libiec61850-node",
3
- "version": "1.0.41",
3
+ "version": "1.0.43",
4
4
  "description": "Node.js addon for IEC 61850 client (MMS, GOOSE) using libiec61850",
5
5
  "main": "index.js",
6
6
  "keywords": [