@amigo9090/ih-libiec61850-node 1.0.37 → 1.0.38

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'); //../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) => {
@@ -6,7 +6,6 @@ const client = new MmsClient((event, data) => {
6
6
 
7
7
  if (event === 'conn' && data.event === 'opened') {
8
8
  console.log('Connection opened, browsing data model...');
9
- // Запускаем асинхронную логику после открытия соединения
10
9
  handleConnectionOpened();
11
10
  }
12
11
 
@@ -33,7 +32,6 @@ const client = new MmsClient((event, data) => {
33
32
  if (data.timestamp) {
34
33
  console.log(` Timestamp: ${data.timestamp}`);
35
34
  }
36
- // data.values - это объект, а не массив
37
35
  Object.entries(data.values).forEach(([ref, value], index) => {
38
36
  const reason = data.reasons[ref];
39
37
  if (reason && reason !== 0) {
@@ -84,17 +82,13 @@ const client = new MmsClient((event, data) => {
84
82
  }
85
83
  });
86
84
 
87
- // Вспомогательная функция сна
88
85
  const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
89
86
 
90
- // Основная асинхронная функция обработки после открытия соединения
91
87
  async function handleConnectionOpened() {
92
88
  try {
93
- // Просмотр модели данных
94
89
  const dataModel = await client.browseDataModel();
95
90
  console.log('Data Model:', util.inspect(dataModel, { depth: null }));
96
91
 
97
- // Извлечение всех датасетов
98
92
  const dataSets = [];
99
93
  dataModel.forEach(ld => {
100
94
  ld.logicalNodes.forEach(ln => {
@@ -105,17 +99,12 @@ async function handleConnectionOpened() {
105
99
  });
106
100
  });
107
101
 
108
- // Пакетное чтение датасетов
109
- //if (dataSets.length > 0) {
110
- // console.log('Reading datasets in batch...');
111
- // const dataSetRefs = dataSets.map(ds => ds.reference);
112
- // await client.readDataSetValues(dataSetRefs);
113
- //}
114
-
115
- // Читаем все DataSet'ы одним вызовом
116
102
  console.log('\nЧтение значений DataSet...');
117
103
  const datasetRefs = dataSets.map(ds => ds.reference);
104
+ console.log('Calling readDataSetValues...');
118
105
  const readResults = await client.readDataSetValues(datasetRefs);
106
+ console.log('readDataSetValues returned');
107
+
119
108
 
120
109
  readResults.forEach((res, idx) => {
121
110
  const ds = dataSets[idx];
@@ -126,39 +115,80 @@ async function handleConnectionOpened() {
126
115
  }
127
116
 
128
117
  console.log(` Значений: ${res.count}, Удаляемые: ${res.isDeletable}`);
118
+
119
+ // Функция для рекурсивного вывода вложенных структур
120
+ const printValue = (value, indent = ' ') => {
121
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
122
+ Object.entries(value).forEach(([key, val]) => {
123
+ if (val && typeof val === 'object' && !Array.isArray(val)) {
124
+ console.log(`${indent}${key}: {`);
125
+ printValue(val, indent + ' ');
126
+ console.log(`${indent}}`);
127
+ } else if (Array.isArray(val)) {
128
+ console.log(`${indent}${key}: [`);
129
+ val.forEach((item, i) => {
130
+ console.log(`${indent} [${i}]:`);
131
+ printValue(item, indent + ' ');
132
+ });
133
+ console.log(`${indent}]`);
134
+ } else {
135
+ console.log(`${indent}${key}: ${util.inspect(val, { colors: true })}`);
136
+ }
137
+ });
138
+ } else {
139
+ console.log(`${indent}${util.inspect(value, { colors: true })}`);
140
+ }
141
+ };
142
+
129
143
  Object.entries(res.values).forEach(([ref, value]) => {
130
- console.log(` ${ref}: ${util.inspect(value, { colors: true })}`);
144
+ console.log(` ${ref}:`);
145
+ printValue(value, ' ');
131
146
  });
132
147
  });
133
148
 
134
- // Пакетное чтение отдельных значений
135
149
  console.log('Reading data...');
136
150
  const dataRefs = [
137
151
  'WAGO61850ServerDevice/XCBR1.Pos[ST]',
138
- 'WAGO61850ServerDevice/GGIO1.Ind.stVal',
152
+ 'WAGO61850ServerDevice/GGIO1.Ind1.stVal',
139
153
  'WAGO61850ServerDevice/CALH12.GrAlm.stVal'
140
154
  ];
141
155
  const readRefResult = await client.readData(dataRefs);
142
- console.log("readRefResult " + util.inspect(readRefResult));
156
+ console.log("readRefResult " + util.inspect(readRefResult, { depth: null }));
143
157
 
144
- // Включение отчётности
145
- const rcbRef = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0101';
158
+ /*const rcbRef = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0101';
146
159
  const dataSetRef = 'WAGO61850ServerDevice/LLN0.DataSet01';
147
160
  console.log(`Enabling reporting for ${rcbRef} with dataset ${dataSetRef}`);
148
- await client.enableReporting(rcbRef, dataSetRef);
161
+ await client.enableReporting(rcbRef, dataSetRef);*/
149
162
 
150
- // Включение отчётности2
151
163
  const rcbRef2 = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0201';
152
164
  const dataSetRef2 = 'WAGO61850ServerDevice/LLN0.DataSet02';
153
165
  console.log(`Enabling reporting for ${rcbRef2} with dataset ${dataSetRef2}`);
154
166
  await client.enableReporting(rcbRef2, dataSetRef2);
155
167
 
168
+ /*console.log('Reading data...');
169
+ const dataRefs = [
170
+ 'A01LD0/Q1_XCBR1.Pos[ST]',
171
+ 'A01LD0/In_GGIO1.Ind1',
172
+ 'A01LD0/CALH1.GrAlm.stVal'
173
+ ];
174
+ const readRefResult = await client.readData(dataRefs);
175
+ console.log("readRefResult " + util.inspect(readRefResult, { depth: null }));
176
+
177
+ const rcbRef = 'A01LD0/LLN0.RP.repTI1';
178
+ const dataSetRef = 'A01LD0/LLN0.TI_ASU';
179
+ console.log(`Enabling reporting for ${rcbRef} with dataset ${dataSetRef}`);
180
+ await client.enableReporting(rcbRef, dataSetRef);
181
+
182
+ const rcbRef2 = 'A01LD0/LLN0.BR.repTS1';
183
+ const dataSetRef2 = 'A01LD0/LLN0.TS_ASU';
184
+ console.log(`Enabling reporting for ${rcbRef2} with dataset ${dataSetRef2}`);
185
+ await client.enableReporting(rcbRef2, dataSetRef2);*/
186
+
156
187
  } catch (err) {
157
188
  console.error('Error in handleConnectionOpened:', err.message);
158
189
  }
159
190
  }
160
191
 
161
- // Главная функция
162
192
  async function main() {
163
193
  try {
164
194
  console.log('Starting client...');
@@ -169,27 +199,18 @@ async function main() {
169
199
  reconnectDelay: 2
170
200
  });
171
201
 
172
- // Ждём открытия соединения (событие будет обработано в колбэке)
173
202
  await sleep(5000);
174
203
 
175
- // Опционально: управление (раскомментируй при необходимости)
176
- // console.log('Performing control operation...');
177
- // await client.controlObject("WAGO61850ServerDevice/XCBR1.Pos", true);
178
- // await sleep(5000);
179
-
180
- // Ожидание данных и отчётов
181
204
  console.log('Waiting for data and reports...');
182
- await sleep(30000);
205
+ await sleep(15000);
183
206
 
184
- // Отключение отчётов
185
- const rcbRef = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0101';
207
+ /*const rcbRef = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0101';
186
208
  console.log(`Disabling reporting for ${rcbRef}`);
187
- await client.disableReporting(rcbRef);
209
+ await client.disableReporting(rcbRef);*/
188
210
 
189
- // Отключение отчётов2
190
- const rcbRef2 = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0102';
191
- console.log(`Disabling reporting for ${rcbRef2}`);
192
- await client.disableReporting(rcbRef2);
211
+ const rcbRef2 = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0201';
212
+ console.log(`Disabling reporting for ${rcbRef2}`);
213
+ await client.disableReporting(rcbRef2);
193
214
 
194
215
  console.log('Client status:', client.getStatus());
195
216
  console.log('Closing client...');
@@ -202,5 +223,4 @@ async function main() {
202
223
  }
203
224
  }
204
225
 
205
- // Запуск
206
226
  main().catch(err => console.error('Fatal error:', err.message));
@@ -0,0 +1,229 @@
1
+ const { MmsClient } = require('../build/Release/addon_iec61850');
2
+ const util = require('util');
3
+
4
+ const client = new MmsClient((event, data) => {
5
+ console.log(`Event: ${event}, Data: ${util.inspect(data, { depth: null })}`);
6
+
7
+ if (event === 'conn' && data.event === 'opened') {
8
+ console.log('Connection opened, browsing data model...');
9
+ handleConnectionOpened();
10
+ }
11
+
12
+ if (event === 'data' && data.type === 'data') {
13
+ if (data.event === 'logicalDevices') {
14
+ console.log(`Logical Devices received: ${util.inspect(data.logicalDevices, { depth: null })}`);
15
+ } else if (data.event === 'dataSetDirectory') {
16
+ console.log(`DataSet Directory for ${data.logicalNodeRef}: ${util.inspect(data.dataSets, { depth: null })}`);
17
+ } else if (data.event === 'dataModel') {
18
+ console.log(`Data Model received: ${util.inspect(data.dataModel, { depth: null })}`);
19
+ } else if (data.event === 'dataSet') {
20
+ console.log(`DataSet received for ${data.datasetRef}: ${util.inspect(data.value, { depth: null })}`);
21
+ } else if (data.event === 'multipleDataSets') {
22
+ console.log(`Multiple DataSets received for ${util.inspect(data.datasetRefs, { depth: null })}:`);
23
+ data.values.forEach((value, index) => {
24
+ if (value.isValid !== false) {
25
+ console.log(` DataSet[${index}]: ${data.datasetRefs[index]}, Value: ${util.inspect(value, { depth: null })}`);
26
+ } else {
27
+ console.log(` DataSet[${index}]: ${data.datasetRefs[index]}, Error: ${value.errorReason}`);
28
+ }
29
+ });
30
+ } else if (data.event === 'report') {
31
+ console.log(`Report received for ${data.rcbRef} (rptId: ${data.rptId}):`);
32
+ if (data.timestamp) {
33
+ console.log(` Timestamp: ${data.timestamp}`);
34
+ }
35
+ Object.entries(data.values).forEach(([ref, value], index) => {
36
+ const reason = data.reasons[ref];
37
+ if (reason && reason !== 0) {
38
+ console.log(` ${ref}: ${util.inspect(value, { depth: null })}, Reason: ${reason}`);
39
+ }
40
+ });
41
+ } else if (data.event === 'batchData') {
42
+ console.log(`Batch Data received for ${util.inspect(data.dataRefs, { depth: null })}:`);
43
+ data.values.forEach((result, index) => {
44
+ if (result.isValid) {
45
+ console.log(` dataRef[${index}]: ${data.dataRefs[index]}, Value: ${util.inspect(result.value, { depth: null })}`);
46
+ } else {
47
+ console.log(` dataRef[${index}]: ${data.dataRefs[index]}, Error: ${result.errorReason}`);
48
+ }
49
+ });
50
+ } else {
51
+ console.log(`Data received for ${data.dataRef || 'undefined'}: ${util.inspect(data.value, { depth: null })}`);
52
+ }
53
+ }
54
+
55
+ if (event === 'data' && data.type === 'error') {
56
+ console.error(`Error received: ${data.reason}`);
57
+ }
58
+
59
+ if (event === 'conn' && data.event === 'reconnecting') {
60
+ console.error(`Reconnection failed: ${data.reason}`);
61
+ if (data.reason.includes('attempt 3')) {
62
+ throw new Error('Max reconnection attempts reached');
63
+ }
64
+ }
65
+
66
+ if (event === 'data' && data.type === 'control') {
67
+ if (data.event === 'reportingEnabled') {
68
+ console.log(`Reporting enabled for ${data.rcbRef}`);
69
+ } else if (data.event === 'reportingDisabled') {
70
+ console.log(`Reporting disabled for ${data.rcbRef}`);
71
+ } else if (data.event === 'dataSetCreated') {
72
+ console.log(`DataSet created: ${data.datasetRef}`);
73
+ } else if (data.event === 'dataSetDeleted') {
74
+ console.log(`DataSet deleted: ${data.datasetRef}`);
75
+ } else if (data.event === 'stateChanged') {
76
+ console.log(`Connection state changed: ${data.state}, isConnected: ${data.isConnected}`);
77
+ }
78
+ }
79
+
80
+ if (event === 'conn' && data.event === 'stateChanged') {
81
+ console.log(`Connection state changed: ${data.state}, isConnected: ${data.isConnected}`);
82
+ }
83
+ });
84
+
85
+ const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
86
+
87
+ async function handleConnectionOpened() {
88
+ try {
89
+ const dataModel = await client.browseDataModel();
90
+ console.log('Data Model:', util.inspect(dataModel, { depth: null }));
91
+
92
+ const dataSets = [];
93
+ dataModel.forEach(ld => {
94
+ ld.logicalNodes.forEach(ln => {
95
+ ln.dataSets.forEach(ds => {
96
+ console.log(`Found dataset: ${ds.reference}`);
97
+ dataSets.push(ds);
98
+ });
99
+ });
100
+ });
101
+
102
+ //для теста
103
+ const dataModel2 = await client.TestDebug();
104
+
105
+ console.log('\nЧтение значений DataSet...');
106
+ const datasetRefs = dataSets.map(ds => ds.reference);
107
+ console.log('Calling readDataSetValues...');
108
+ const readResults = await client.readDataSetValues(datasetRefs);
109
+ console.log('readDataSetValues returned');
110
+
111
+
112
+ readResults.forEach((res, idx) => {
113
+ const ds = dataSets[idx];
114
+ console.log(`\nDataSet: ${res.datasetRef}`);
115
+ if (!res.isValid) {
116
+ console.error(' Ошибка:', res.errorReason);
117
+ return;
118
+ }
119
+
120
+ console.log(` Значений: ${res.count}, Удаляемые: ${res.isDeletable}`);
121
+
122
+ // Функция для рекурсивного вывода вложенных структур
123
+ const printValue = (value, indent = ' ') => {
124
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
125
+ Object.entries(value).forEach(([key, val]) => {
126
+ if (val && typeof val === 'object' && !Array.isArray(val)) {
127
+ console.log(`${indent}${key}: {`);
128
+ printValue(val, indent + ' ');
129
+ console.log(`${indent}}`);
130
+ } else if (Array.isArray(val)) {
131
+ console.log(`${indent}${key}: [`);
132
+ val.forEach((item, i) => {
133
+ console.log(`${indent} [${i}]:`);
134
+ printValue(item, indent + ' ');
135
+ });
136
+ console.log(`${indent}]`);
137
+ } else {
138
+ console.log(`${indent}${key}: ${util.inspect(val, { colors: true })}`);
139
+ }
140
+ });
141
+ } else {
142
+ console.log(`${indent}${util.inspect(value, { colors: true })}`);
143
+ }
144
+ };
145
+
146
+ Object.entries(res.values).forEach(([ref, value]) => {
147
+ console.log(` ${ref}:`);
148
+ printValue(value, ' ');
149
+ });
150
+ });
151
+
152
+ console.log('Reading data...');
153
+ const dataRefs = [
154
+ 'WAGO61850ServerDevice/XCBR1.Pos[ST]',
155
+ 'WAGO61850ServerDevice/GGIO1.Ind1.stVal',
156
+ 'WAGO61850ServerDevice/CALH12.GrAlm.stVal'
157
+ ];
158
+ const readRefResult = await client.readData(dataRefs);
159
+ console.log("readRefResult " + util.inspect(readRefResult, { depth: null }));
160
+
161
+ /*const rcbRef = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0101';
162
+ const dataSetRef = 'WAGO61850ServerDevice/LLN0.DataSet01';
163
+ console.log(`Enabling reporting for ${rcbRef} with dataset ${dataSetRef}`);
164
+ await client.enableReporting(rcbRef, dataSetRef);*/
165
+
166
+ const rcbRef2 = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0201';
167
+ const dataSetRef2 = 'WAGO61850ServerDevice/LLN0.DataSet02';
168
+ console.log(`Enabling reporting for ${rcbRef2} with dataset ${dataSetRef2}`);
169
+ await client.enableReporting(rcbRef2, dataSetRef2);
170
+
171
+ /*console.log('Reading data...');
172
+ const dataRefs = [
173
+ 'A01LD0/Q1_XCBR1.Pos[ST]',
174
+ 'A01LD0/In_GGIO1.Ind1',
175
+ 'A01LD0/CALH1.GrAlm.stVal'
176
+ ];
177
+ const readRefResult = await client.readData(dataRefs);
178
+ console.log("readRefResult " + util.inspect(readRefResult, { depth: null }));
179
+
180
+ const rcbRef = 'A01LD0/LLN0.RP.repTI1';
181
+ const dataSetRef = 'A01LD0/LLN0.TI_ASU';
182
+ console.log(`Enabling reporting for ${rcbRef} with dataset ${dataSetRef}`);
183
+ await client.enableReporting(rcbRef, dataSetRef);
184
+
185
+ const rcbRef2 = 'A01LD0/LLN0.BR.repTS1';
186
+ const dataSetRef2 = 'A01LD0/LLN0.TS_ASU';
187
+ console.log(`Enabling reporting for ${rcbRef2} with dataset ${dataSetRef2}`);
188
+ await client.enableReporting(rcbRef2, dataSetRef2);*/
189
+
190
+ } catch (err) {
191
+ console.error('Error in handleConnectionOpened:', err.message);
192
+ }
193
+ }
194
+
195
+ async function main() {
196
+ try {
197
+ console.log('Starting client...');
198
+ await client.connect({
199
+ ip: '192.168.0.142',
200
+ port: 102,
201
+ clientID: 'mms_client1',
202
+ reconnectDelay: 2
203
+ });
204
+
205
+ await sleep(5000);
206
+
207
+ console.log('Waiting for data and reports...');
208
+ await sleep(15000);
209
+
210
+ /*const rcbRef = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0101';
211
+ console.log(`Disabling reporting for ${rcbRef}`);
212
+ await client.disableReporting(rcbRef);*/
213
+
214
+ const rcbRef2 = 'WAGO61850ServerDevice/LLN0.RP.ReportBlock0201';
215
+ console.log(`Disabling reporting for ${rcbRef2}`);
216
+ await client.disableReporting(rcbRef2);
217
+
218
+ console.log('Client status:', client.getStatus());
219
+ console.log('Closing client...');
220
+ await client.close();
221
+ console.log('Client closed.');
222
+
223
+ } catch (err) {
224
+ console.error('Main error:', err.message);
225
+ await client.close().catch(e => console.error('Close error:', e.message));
226
+ }
227
+ }
228
+
229
+ 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.37",
3
+ "version": "1.0.38",
4
4
  "description": "Node.js addon for IEC 61850 client (MMS, GOOSE) using libiec61850",
5
5
  "main": "index.js",
6
6
  "keywords": [