@tier0/node-opc-da 1.0.7

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.
@@ -0,0 +1,285 @@
1
+ //@ts-check
2
+ /*
3
+ Copyright: (c) 2019, Guilherme Francescon Cittolin <gfcittolin@gmail.com>
4
+ GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
5
+ */
6
+
7
+ const constants = require('./constants.js');
8
+ const {CallBuilder, ComString, ComValue, Types, Pointer, Flags} = require('node-dcom');
9
+ const EnumString = require('./enumString');
10
+ const util = require('util');
11
+ const debug = util.debuglog('node-opc-da');
12
+
13
+ /**
14
+ * Represents an OPC Browser
15
+ */
16
+ class OPCBrowser {
17
+
18
+ constructor() {
19
+ this._comObj = null;
20
+ }
21
+
22
+ /**
23
+ *
24
+ * @param {*} unknown
25
+ * @returns {Promise<?>}
26
+ */
27
+ async init(unknown) {
28
+ debug("Initing OPCBrowser...");
29
+ if (this._comObj) throw new Error("Already initialized");
30
+
31
+ this._comObj = await unknown.queryInterface(constants.iid.IOPCBrowseServerAddressSpace_IID);
32
+
33
+ debug("OPCBrowser successfully created.");
34
+ }
35
+
36
+ async end() {
37
+ debug("Destroying OPCBrowser...");
38
+ if (!this._comObj) return;
39
+
40
+ let obj = this._comObj;
41
+ this._comObj = null;
42
+ await obj.release();
43
+ debug("OPCBrowser successfully destroyed.");
44
+ }
45
+
46
+ /**
47
+ *
48
+ * @returns {Promise<number>}
49
+ * @opNum 0
50
+ */
51
+ async queryOrganization() {
52
+ debug("Querying OPCServer for items organization...");
53
+ if (!this._comObj) throw new Error("Not initialized");
54
+
55
+ let callObject = new CallBuilder(true);
56
+ callObject.setOpnum(0);
57
+
58
+ callObject.addOutParamAsType(Types.SHORT, Flags.FLAG_NULL);
59
+
60
+ let resultObj = await this._comObj.call(callObject);
61
+
62
+ let hresult = resultObj.hresult;
63
+ let result = resultObj.getResults();
64
+ if (hresult != 0) {
65
+ if (result.lenght == 0)
66
+ throw new Error(String(hresult));
67
+ else
68
+ debug(String(new Error(String(hresult))));
69
+ }
70
+ debug("Item organization obtained.");
71
+ return result[0];
72
+ }
73
+
74
+ /**
75
+ *
76
+ * @param {string} position
77
+ * @param {number} direction
78
+ * @returns {Promise<void>}
79
+ * @opNum 1
80
+ */
81
+ async changePosition(position, direction) {
82
+ debug("Changing browsing position to " + direction);
83
+ if (!this._comObj) throw new Error("Not initialized");
84
+
85
+ let callObject = new CallBuilder(true);
86
+ callObject.setOpnum(1);
87
+
88
+ callObject.addInParamAsShort(direction, Flags.FLAG_NULL);
89
+ callObject.addInParamAsString(position, Flags.FLAG_REPRESENTATION_STRING_LPWSTR);
90
+
91
+ let resultObj = await this._comObj.call(callObject);
92
+
93
+ let hresult = resultObj.hresult;
94
+ let result = resultObj.getResults();
95
+ if (hresult != 0) {
96
+ if (result.lenght == 0)
97
+ throw new Error(String(hresult));
98
+ else {
99
+ if (hresult == 1) {
100
+ if (direction == constants.opc.browse.direction.TO)
101
+ debug("Already on top directory.");
102
+ else if (direction == constants.opc.browse.direction.DOWN)
103
+ debug("There is not directory to go down to.");
104
+ else if (direction == constants.opc.browse.direction.UP)
105
+ debug("There is not directory to go up to. Already on top directory");
106
+ } else if (hresult == 0x80004001) {
107
+ debug ("Browsing is not implemented by the server");
108
+ }
109
+ }
110
+ }
111
+ debug("Browsing position successfully changed.");
112
+ }
113
+
114
+ /**
115
+ *
116
+ * @param {number} type
117
+ * @param {string} [filter=""]
118
+ * @param {number} [dataType=0]
119
+ * @param {number} [accessRights=0]
120
+ * @returns {Promise<EnumString>}
121
+ * @opNum 2
122
+ */
123
+ async browse(type, filter, accessRights, dataType) {
124
+ debug("Browsing OPCServer with type: " + type + " filter: " + filter + " accessRights: " + accessRights + " dataType: " + dataType + "...");
125
+ if (!this._comObj) throw new Error("Not initialized");
126
+
127
+ let callObject = new CallBuilder(true);
128
+ callObject.setOpnum(2);
129
+
130
+ callObject.addInParamAsShort(type, Flags.FLAG_NULL);
131
+ callObject.addInParamAsString(filter, Flags.FLAG_REPRESENTATION_STRING_LPWSTR);
132
+ callObject.addInParamAsShort(dataType, Flags.FLAG_NULL);
133
+ callObject.addInParamAsInt(accessRights, Flags.FLAG_NULL);
134
+ callObject.addOutParamAsType(Types.COMOBJECT, Flags.FLAG_NULL);
135
+
136
+ let resultObj = await this._comObj.call(callObject);
137
+
138
+ let hresult = resultObj.hresult;
139
+ let result = resultObj.getResults();
140
+ if (hresult != 0) {
141
+ if (result.lenght == 0)
142
+ throw new Error(String(hresult));
143
+ else {
144
+ if (hresult == 1) {
145
+ if (type == constants.opc.browse.type.LEAF)
146
+ debug("No more leafs found for the current level.");
147
+ else if (type = constants.opc.browse.type.BRANCH)
148
+ debug("No more branches found for the current level.")
149
+ } else if (hresult == 0x80004001) {
150
+ debug("Browsing is not implemented by the server");
151
+ }
152
+ }
153
+ }
154
+
155
+ let enumResults = new EnumString();
156
+ await enumResults.init(result[0].getValue());
157
+ debug("Browsing request successfully executed.");
158
+ return enumResults;
159
+ }
160
+
161
+ /**
162
+ * Gets the complete item id from an item at the local position.
163
+ *
164
+ * Browsing a hierarchical namespace the browse method will return items based on the
165
+ * local level in the namespace. So actually only the last part of the item ID hierarchy
166
+ * is returned. In order to convert this to the full item ID one can use this method. It
167
+ * will only work if the browser is still at the position in question.
168
+ *
169
+ * @param {string} item the local item
170
+ * @returns {Promise<string>} the complete item ID
171
+ * @opNum 3
172
+ */
173
+ async getItemID(item) {
174
+ debug("Querying OPCServer for itemID: " + item + "...");
175
+ if (!this._comObj) throw new Error("Not initialized");
176
+
177
+ let callObject = new CallBuilder(true);
178
+ callObject.setOpnum(3);
179
+
180
+ let strValue = new ComValue(new ComString(Flags.FLAG_REPRESENTATION_STRING_LPWSTR), Types.COMSTRING);
181
+ let strPointerValue = new ComValue(new Pointer(strValue), Types.POINTER);
182
+ callObject.addInParamAsString(item, Flags.FLAG_REPRESENTATION_STRING_LPWSTR );
183
+ callObject.addOutParamAsObject(strPointerValue, Flags.FLAG_NULL);
184
+
185
+ let resultObj = await this._comObj.call(callObject);
186
+
187
+ let hresult = resultObj.hresult;
188
+ let result = resultObj.getResults();
189
+ if (hresult != 0) {
190
+ if (result.lenght == 0)
191
+ throw new Error(String(hresult));
192
+ else
193
+ debug(new Error(String(hresult)));
194
+ }
195
+
196
+ let resultPtr = result[0].getValue();
197
+ let resultPtrRef = resultPtr.getReferent();
198
+ debug("Item request successfully executed.");
199
+ return resultPtrRef.getString();
200
+ }
201
+
202
+ /**
203
+ * Returns the possible access paths for an item
204
+ *
205
+ * @param {string} itemID the item to query
206
+ * @returns {Promise<EnumString>} the complete item ID
207
+ * @opNum 4
208
+ */
209
+ async browseAccessPaths(itemID) {
210
+ debug("Querying OPCServer for browseAcessPaths for the item " + itemID + "...");
211
+ if (!this._comObj) throw new Error("Not initialized");
212
+
213
+ let callObject = new CallBuilder(true);
214
+ callObject.setOpnum(4);
215
+
216
+ callObject.addInParamAsString(itemID, Flags.FLAG_REPRESENTATION_STRING_LPWSTR);
217
+ callObject.addOutParamAsType (Types.COMOBJECT, Flags.FLAG_NULL );
218
+
219
+ let resultObj = await this._comObj.call(callObject);
220
+
221
+ let hresult = resultObj.hresult;
222
+ let result = resultObj.getResults();
223
+ if (hresult != 0) {
224
+ if (result.lenght == 0)
225
+ throw new Error(String(hresult));
226
+ else
227
+ debug(new Error(String(hresult)));
228
+ }
229
+
230
+ let enumResults = new EnumString();
231
+ await enumResults.init(result[0]);
232
+ debug("Item browseAccessPaths successfully obtained.");
233
+ return enumResults;
234
+ }
235
+
236
+ // -------
237
+
238
+ /**
239
+ * @returns {Promise<Array<string>>} an array with all items in a flat address space
240
+ */
241
+ async browseAllFlat() {
242
+ debug("Browsing OPCServer on Flat mode...");
243
+ await this.changePosition(null, constants.opc.browse.direction.TO);
244
+ let enumItems = await this.browse(constants.opc.browse.type.FLAT)
245
+ .catch(function(reject) {
246
+ throw reject;
247
+ });
248
+
249
+ let result = await enumItems.asArray();
250
+ debug("Successfully browsed OPCServer and obtained " + result.length + " items.");
251
+ return result;
252
+ }
253
+
254
+ /**
255
+ * @returns {Promise<object>} an object representing the hierarchy of items
256
+ */
257
+ async browseAllTree() {
258
+ await this.changePosition(null, constants.opc.browse.direction.TO);
259
+ return await this.browseLevel();
260
+ }
261
+
262
+ /**
263
+ * change the browsing level
264
+ */
265
+ async browseLevel() {
266
+ let res = {}
267
+
268
+ // get items on this level
269
+ let enumItems = await this.browse(constants.opc.browse.type.LEAF);
270
+ let items = await enumItems.asArray();
271
+ for (const item of items) {
272
+ res[item] = await this.getItemID(item);
273
+ }
274
+ let enumBranches = await this.browse(constants.opc.browse.type.BRANCH);
275
+ let branches = await enumBranches.asArray();
276
+ for (const branch of branches) {
277
+ await this.changePosition(branch, constants.opc.browse.direction.DOWN);
278
+ res[branch] = await this.browseLevel();
279
+ await this.changePosition(null, constants.opc.browse.direction.UP);
280
+ }
281
+ return res;
282
+ }
283
+ }
284
+
285
+ module.exports = OPCBrowser;
@@ -0,0 +1,84 @@
1
+ //@ts-check
2
+ /*
3
+ Copyright: (c) 2019, Guilherme Francescon Cittolin <gfcittolin@gmail.com>
4
+ GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
5
+ */
6
+
7
+ const constants = require('./constants.js');
8
+
9
+ /**
10
+ * Represents an OPC Server
11
+ */
12
+ class OPCCommon {
13
+
14
+ constructor() {
15
+ this._comObj = null;
16
+ }
17
+
18
+ /**
19
+ *
20
+ * @param {*} unknown
21
+ * @returns {Promise<?>}
22
+ */
23
+ async init(unknown) {
24
+ if (this._comObj) throw new Error("Already initialized");
25
+
26
+ this._comObj = await unknown.queryInterface(constants.iid.IOPCCommon_IID);
27
+ }
28
+
29
+ async end() {
30
+ if (!this._comObj) return;
31
+
32
+ let obj = this._comObj;
33
+ this._comObj = null;
34
+ await obj.release();
35
+ }
36
+
37
+ /**
38
+ *
39
+ * @param {number} localeId
40
+ * @opNum 0
41
+ */
42
+ async setLocaleID(localeId) {
43
+ if (!this._comObj) throw new Error("Not initialized");
44
+
45
+ }
46
+
47
+ /**
48
+ * @returns the current localeID
49
+ * @opNum 1
50
+ */
51
+ async getLocaleID() {
52
+ if (!this._comObj) throw new Error("Not initialized");
53
+ }
54
+
55
+ /**
56
+ * @returns the available localeIDs
57
+ * @opNum 2
58
+ */
59
+ async queryAvailableLocaleIDs() {
60
+ if (!this._comObj) throw new Error("Not initialized");
61
+ }
62
+
63
+ /**
64
+ *
65
+ * @param {number} error
66
+ * @param {number} [localeID]
67
+ * @returns a descriptive error string for the error code
68
+ * @opNum 3
69
+ */
70
+ async getErrorString(error, localeID) {
71
+ if (!this._comObj) throw new Error("Not initialized");
72
+ }
73
+
74
+ /**
75
+ *
76
+ * @param {string} name the client name
77
+ * @opNum 4
78
+ */
79
+ async setClientName(name) {
80
+ if (!this._comObj) throw new Error("Not initialized");
81
+ }
82
+ }
83
+
84
+ module.exports = OPCCommon;
@@ -0,0 +1,248 @@
1
+ //@ts-check
2
+ /*
3
+ Copyright: (c) 2019, Guilherme Francescon Cittolin <gfcittolin@gmail.com>
4
+ GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
5
+ */
6
+
7
+ const constants = require('./constants.js');
8
+ const OPCItemManager = require('./opcItemManager.js');
9
+ const OPCSyncIO = require('./opcSyncIO.js');
10
+ const OPCAsyncIO = require('./opcAsyncIO.js');
11
+ const util = require('util');
12
+ const debug = util.debuglog('node-opc-da');
13
+ const { EventEmitter } = require('events');
14
+
15
+ const { CallBuilder, ComString, ComValue, Flags, Pointer, types} = require('node-dcom');
16
+
17
+
18
+ /**
19
+ * Group properties
20
+ * @typedef {object} GroupProperties
21
+ * @property {number} updateRate
22
+ * @property {boolean} active
23
+ * @property {number} timeBias
24
+ * @property {number} deadband
25
+ * @property {number} localeID
26
+ * @property {number} [clientHandle]
27
+ * @property {number} [serverHandle]
28
+ *
29
+ */
30
+
31
+ /**
32
+ * Represents an OPC Server
33
+ * @emits data
34
+ */
35
+ class OPCGroupStateManager extends EventEmitter {
36
+
37
+ constructor() {
38
+ super();
39
+
40
+ this._opcItemManager = null;
41
+ this._syncIO = null;
42
+ this._asyncIO = null;
43
+ }
44
+
45
+ /**
46
+ *
47
+ * @param {*} unknown
48
+ * @returns {Promise<?>}
49
+ */
50
+ async init(unknown) {
51
+ debug("Initing opcGroupStateManager...");
52
+ if (this._comObj) throw new Error("Already initialized");
53
+
54
+ this._comObj = await unknown.queryInterface(constants.iid.IOPCGroupStateMgt_IID);
55
+ debug("opcGroupStateManager successfully inited");
56
+ }
57
+
58
+ async end() {
59
+ debug("Destryoing opcGroupStateManager...")
60
+ if (!this._comObj) return;
61
+
62
+ let obj = this._comObj;
63
+ let opcItemManager = this._opcItemManager;
64
+ let syncIO = this._syncIO;
65
+ let asyncIO = this._asyncIO;
66
+ this._comObj = null;
67
+ this._opcItemManager = null;
68
+ this._syncIO = null;
69
+ this._asyncIO = null;
70
+
71
+ //TODO maybe paralelize this with Promise.all
72
+ if (opcItemManager) await opcItemManager.end();
73
+ if (syncIO) await syncIO.end();
74
+ if (asyncIO) await asyncIO.end();
75
+ await obj.release();
76
+
77
+ debug("opcGroupStateManager successfully desroyed.");
78
+ }
79
+
80
+ /**
81
+ * @returns {Object<{name: string}, {state: GroupProperties}}>}
82
+ */
83
+ async getState() {
84
+ debug("Querying OPCServer for the current state of the group...");
85
+ if (!this._comObj) throw new Error("Not initialized");
86
+
87
+ let callObject = new CallBuilder(true);
88
+ callObject.setOpnum(0);
89
+
90
+ let namePtr = new Pointer(new ComValue(new ComString(Flags.FLAG_REPRESENTATION_STRING_LPWSTR), types.COMSTRING));
91
+
92
+ callObject.addOutParamAsType(types.INTEGER, Flags.FLAG_NULL);
93
+ callObject.addOutParamAsType(types.BOOLEAN, Flags.FLAG_NULL);
94
+ callObject.addOutParamAsObject(new ComValue(namePtr, types.POINTER), Flags.FLAG_NULL);
95
+ callObject.addOutParamAsType(types.INTEGER, Flags.FLAG_NULL);
96
+ callObject.addOutParamAsType(types.FLOAT, Flags.FLAG_NULL);
97
+ callObject.addOutParamAsType(types.INTEGER, Flags.FLAG_NULL);
98
+ callObject.addOutParamAsType(types.INTEGER, Flags.FLAG_NULL);
99
+ callObject.addOutParamAsType(types.INTEGER, Flags.FLAG_NULL);
100
+
101
+ let result = await this._comObj.call(callObject);
102
+
103
+ debug("Group State successfully obtained.");
104
+ return {
105
+ name: result[2].getReferent().getString(),
106
+ state: {
107
+ updateRate: result[0],
108
+ active: result[1],
109
+ timeBias: result[3],
110
+ deadband: result[4],
111
+ localeID: result[5],
112
+ clientHandle: result[6],
113
+ serverHandle: result[7]
114
+ }
115
+ }
116
+ }
117
+
118
+ /**
119
+ *
120
+ * @param {GroupProperties} state
121
+ * @returns {Promise<number>} the granted update rate
122
+ * @opNum 1
123
+ */
124
+ async setState(state) {
125
+ debug("Querying OPCServer to set the group properties: " + state);
126
+ if (!this._comObj) throw new Error("Not initialized");
127
+
128
+ let callObject = new CallBuilder(true);
129
+ callObject.setOpnum(1);
130
+
131
+ let activeCV = state.active === null ? null : new ComValue(state.active ? 1 : 0, types.INTEGER);
132
+
133
+ callObject.addInParamAsPointer(new Pointer(new ComValue(state.updateRate, types.INTEGER)), Flags.FLAG_NULL);
134
+ callObject.addInParamAsPointer(new Pointer(activeCV), Flags.FLAG_NULL);
135
+ callObject.addInParamAsPointer(new Pointer(new ComValue(state.timeBias, types.INTEGER)), Flags.FLAG_NULL);
136
+ callObject.addInParamAsPointer(new Pointer(new ComValue(state.deadband, types.FLOAT)), Flags.FLAG_NULL);
137
+ callObject.addInParamAsPointer(new Pointer(new ComValue(state.localeID, types.INTEGER)), Flags.FLAG_NULL);
138
+ callObject.addInParamAsPointer(new Pointer(new ComValue(state.clientHandle, types.INTEGER)), Flags.FLAG_NULL);
139
+
140
+ callObject.addOutParamAsType(types.INTEGER, Flags.FLAG_NULL);
141
+
142
+ let result = await this._comObj.call(callObject);
143
+ debug("Group Properties sucessfully set.");
144
+ return result[0];
145
+ }
146
+
147
+ /**
148
+ *
149
+ * @param {string} name
150
+ * @returns {Promise<void>}
151
+ * @opNum 2
152
+ */
153
+ async setName(name) {
154
+ debug("Setting group name to: " + name + "...");
155
+ if (!this._comObj) throw new Error("Not initialized");
156
+
157
+ let callObject = new CallBuilder(true);
158
+ callObject.setOpnum(2);
159
+
160
+ callObject.addInParamAsString(name, Flags.FLAG_REPRESENTATION_STRING_LPWSTR);
161
+
162
+ await this._comObj.call(callObject);
163
+ debug("Group Name successfully set");
164
+ }
165
+
166
+ /**
167
+ *
168
+ * @param {string} name
169
+ * @returns {Promise<OPCGroupStateManager>}
170
+ * @opNum 3
171
+ */
172
+ async clone(name) {
173
+ debug("Cloning group named: " + name + "...");
174
+ if (!this._comObj) throw new Error("Not initialized");
175
+
176
+ let callObject = new CallBuilder(true);
177
+ callObject.setOpnum(3);
178
+
179
+ callObject.addInParamAsString(name, Flags.FLAG_REPRESENTATION_STRING_LPWSTR);
180
+ callObject.addInParamAsUUID(constants.iid.IOPCGroupStateMgt_IID, Flags.FLAG_NULL);
181
+ callObject.addOutParamAsType(types.COMOBJECT, Flags.FLAG_NULL);
182
+
183
+ let result = await this._comObj.call(callObject);
184
+
185
+ let group = new OPCGroupStateManager();
186
+ await group.init(result[0]);
187
+
188
+ return group;
189
+ }
190
+
191
+ /**
192
+ * enables receiving events to this group
193
+ *
194
+ * @returns {Promise<void>}
195
+ */
196
+ async atach() {
197
+ throw new Error("Not yet supported");
198
+ }
199
+
200
+ /**
201
+ * @returns {Promise<OPCItemManager>}
202
+ */
203
+ async getItemManager() {
204
+ debug("Querying server for an ItemManager for the current group...");
205
+ if (!this._comObj) throw new Error("Not initialized");
206
+
207
+ if (!this._opcItemManager) {
208
+ let opcItemManager = new OPCItemManager();
209
+ await opcItemManager.init(this._comObj);
210
+ this._opcItemManager = opcItemManager;
211
+ }
212
+ debug("ItemManager successfully obtained.");
213
+ return this._opcItemManager;
214
+ }
215
+
216
+ /**
217
+ * @returns {Promise<OPCSyncIO>}
218
+ */
219
+ async getSyncIO() {
220
+ debug("Querying OPCServer for a SyncIO object...");
221
+ if (!this._comObj) throw new Error("Not initialized");
222
+
223
+ if (!this._syncIO) {
224
+ let syncIO = new OPCSyncIO();
225
+ await syncIO.init(this._comObj);
226
+ this._syncIO = syncIO;
227
+ }
228
+ debug("SyncIO object successfully obtained.");
229
+ return this._syncIO;
230
+ }
231
+
232
+ /**
233
+ * @returns {Promise<OPCAsyncIO>}
234
+ */
235
+ async getAsyncIO2() {
236
+ if (!this._comObj) throw new Error("Not initialized");
237
+
238
+ if (!this._asyncIO) {
239
+ let asyncIO = new OPCAsyncIO();
240
+ await asyncIO.init(this._comObj);
241
+ this._asyncIO = asyncIO;
242
+ }
243
+ return this._asyncIO;
244
+ }
245
+
246
+ }
247
+
248
+ module.exports = OPCGroupStateManager;
@@ -0,0 +1,60 @@
1
+ //@ts-check
2
+ /*
3
+ Copyright: (c) 2019, Guilherme Francescon Cittolin <gfcittolin@gmail.com>
4
+ GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
5
+ */
6
+
7
+ const constants = require('./constants.js');
8
+
9
+ /**
10
+ * Represents an OPC Item I/O object
11
+ */
12
+ class OPCItemIO {
13
+
14
+ constructor() {
15
+ this._comObj = null;
16
+ }
17
+
18
+ /**
19
+ *
20
+ * @param {*} unknown
21
+ * @returns {Promise<?>}
22
+ */
23
+ async init(unknown) {
24
+ if (this._comObj) throw new Error("Already initialized");
25
+
26
+ this._comObj = await unknown.queryInterface(constants.iid.IOPCItemIO_IID);
27
+ }
28
+
29
+ async end() {
30
+ if (!this._comObj) return;
31
+
32
+ let obj = this._comObj;
33
+ this._comObj = null;
34
+ await obj.release();
35
+ }
36
+
37
+ /**
38
+ *
39
+ * @param {object[]} items
40
+ * @param {string} items[].itemID
41
+ * @param {number} items[].maxAge
42
+ * @returns {Promise<?>}
43
+ * @opNum 0
44
+ */
45
+ async read(items) {
46
+ if (!this._comObj) throw new Error("Not initialized");
47
+ }
48
+
49
+ /**
50
+ *
51
+ * @param {object[]} items ????
52
+ * @returns {Promise<?>}
53
+ * @opNum 1
54
+ */
55
+ async writeVQT(items) {
56
+ if (!this._comObj) throw new Error("Not initialized");
57
+ }
58
+ }
59
+
60
+ module.exports = OPCItemIO;