@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.
- package/LICENSE +201 -0
- package/README.md +171 -0
- package/docs/opcda.idl +1166 -0
- package/package.json +30 -0
- package/src/constants.js +212 -0
- package/src/enumString.js +161 -0
- package/src/filetime.js +79 -0
- package/src/index.js +62 -0
- package/src/opcAsyncIO.js +102 -0
- package/src/opcBrowser.js +285 -0
- package/src/opcCommon.js +84 -0
- package/src/opcGroupStateManager.js +248 -0
- package/src/opcItemIO.js +60 -0
- package/src/opcItemManager.js +415 -0
- package/src/opcItemProperties.js +102 -0
- package/src/opcServer.js +447 -0
- package/src/opcSyncIO.js +213 -0
- package/src/opctypes.js +116 -0
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tier0/node-opc-da",
|
|
3
|
+
"version": "1.0.7",
|
|
4
|
+
"description": "A library to communicate with OPC-DA servers",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/FREEZONEX/node-opc-da.git"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"opc",
|
|
15
|
+
"opc-da",
|
|
16
|
+
"automation",
|
|
17
|
+
"plc",
|
|
18
|
+
"hardware"
|
|
19
|
+
],
|
|
20
|
+
"author": "Guilherme Francescon <guilherme.francescon@netsmarttech.com>",
|
|
21
|
+
"license": "Apache-2.0",
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@tier0/node-dcom": "^1.2.0",
|
|
27
|
+
"random": "^2.1.1",
|
|
28
|
+
"long": "^4.0.0"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/src/constants.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
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 = {
|
|
8
|
+
clsid: {
|
|
9
|
+
OPCServerList_CLSID: "13486D51-4821-11D2-A494-3CB306C10000"
|
|
10
|
+
},
|
|
11
|
+
iid: {
|
|
12
|
+
IConnectionPointContainer_IID: "B196B284-BAB4-101A-B69C-00AA00341D07",
|
|
13
|
+
IConnectionPoint_IID: "B196B286-BAB4-101A-B69C-00AA00341D07",
|
|
14
|
+
IOPCCommon_IID: "F31DFDE2-07B6-11D2-B2D8-0060083BA1FB",
|
|
15
|
+
IEnumString_IID: "00000101-0000-0000-C000-000000000046",
|
|
16
|
+
IEnumGUID_IID: "0002E000-0000-0000-C000-000000000046",
|
|
17
|
+
IOPCServer_IID: "39C13A4D-011E-11D0-9675-0020AFD8ADB3",
|
|
18
|
+
IOPCGroupStateMgt_IID: "39C13A50-011E-11D0-9675-0020AFD8ADB3",
|
|
19
|
+
IOPCBrowse_IID: "39227004-A18F-4B57-8B0A-5235670F4468",
|
|
20
|
+
IOPCBrowseServerAddressSpace_IID: "39C13A4F-011E-11D0-9675-0020AFD8ADB3",
|
|
21
|
+
IOPCItemMgt_IID: "39C13A54-011E-11D0-9675-0020AFD8ADB3",
|
|
22
|
+
IOPCItemProperties_IID: "39C13A72-011E-11D0-9675-0020AFD8ADB3",
|
|
23
|
+
IOPCItemIO_IID: "85C0B427-2893-4CBC-BD78-E5FC5146F08F",
|
|
24
|
+
IOPCDataCallback_IID: "39C13A70-011E-11D0-9675-0020AFD8ADB3",
|
|
25
|
+
IOPCAsyncIO2_IID: "39C13A71-011E-11D0-9675-0020AFD8ADB3",
|
|
26
|
+
IOPCSyncIO_IID: "39C13A52-011E-11D0-9675-0020AFD8ADB3",
|
|
27
|
+
IOPCServerList_IID: "13486D50-4821-11D2-A494-3CB306C10000"
|
|
28
|
+
},
|
|
29
|
+
category: {
|
|
30
|
+
OPCDAServer10: "63D5F430-CFE4-11d1-B2C8-0060083BA1FB",
|
|
31
|
+
OPCDAServer20: "63D5F432-CFE4-11d1-B2C8-0060083BA1FB",
|
|
32
|
+
OPCDAServer30: "CC603642-66D7-48f1-B69A-B625E73652D7",
|
|
33
|
+
XMLDAServer10: "3098EDA4-A006-48b2-A27F-247453959408"
|
|
34
|
+
},
|
|
35
|
+
opc: {
|
|
36
|
+
browse: {
|
|
37
|
+
direction: {
|
|
38
|
+
UNKNOWN: 0,
|
|
39
|
+
UP: 1,
|
|
40
|
+
DOWN: 2,
|
|
41
|
+
TO: 3
|
|
42
|
+
},
|
|
43
|
+
type: {
|
|
44
|
+
UNKNOWN: 0,
|
|
45
|
+
BRANCH: 1,
|
|
46
|
+
LEAF: 2,
|
|
47
|
+
FLAT: 3
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
dataSource: {
|
|
51
|
+
UNKNOWN: 0,
|
|
52
|
+
CACHE: 1,
|
|
53
|
+
DEVICE: 2
|
|
54
|
+
},
|
|
55
|
+
scope: {
|
|
56
|
+
UNKNOWN: 0,
|
|
57
|
+
PRIVATE_CONNECTIONS: 1,
|
|
58
|
+
PUBLIC_CONNECTIONS: 2,
|
|
59
|
+
ALL_CONNECTIONS: 3,
|
|
60
|
+
PRIVATE: 4,
|
|
61
|
+
PUBLIC: 5,
|
|
62
|
+
ALL: 6
|
|
63
|
+
},
|
|
64
|
+
namespaceType: {
|
|
65
|
+
UNKNOWN: 0,
|
|
66
|
+
HIERARCHIAL: 1,
|
|
67
|
+
FLAT: 2
|
|
68
|
+
},
|
|
69
|
+
state: {
|
|
70
|
+
UNKNOWN: 0,
|
|
71
|
+
RUNNING: 1,
|
|
72
|
+
FAILED: 2,
|
|
73
|
+
NOCONFIG: 3,
|
|
74
|
+
SUSPENDED: 4,
|
|
75
|
+
TEST: 5,
|
|
76
|
+
COMM_FAULT: 6
|
|
77
|
+
},
|
|
78
|
+
stateLabel: {
|
|
79
|
+
"0": "unknown",
|
|
80
|
+
"1": "running",
|
|
81
|
+
"2": "failed",
|
|
82
|
+
"3": "noconfig",
|
|
83
|
+
"4": "suspended",
|
|
84
|
+
"5": "test",
|
|
85
|
+
"6": "comm_fault"
|
|
86
|
+
},
|
|
87
|
+
error: {
|
|
88
|
+
OPCInvalidHandle: 3221487617,
|
|
89
|
+
OPCBadType: 3221487620,
|
|
90
|
+
OPCPublic: 3221487621,
|
|
91
|
+
OPCBadRights: 3221487622,
|
|
92
|
+
OPCUnknownItemID: 3221487623,
|
|
93
|
+
OPCInvalidItemID: 3221487624,
|
|
94
|
+
OPCInvalidFilter: 3221487625,
|
|
95
|
+
OPCUnknownPath: 3221487626,
|
|
96
|
+
OPCRange: 3221487627,
|
|
97
|
+
OPCDuplicateName: 3221487628,
|
|
98
|
+
OPCUnsupportedRate: 262157,
|
|
99
|
+
OPCClamp: 262158,
|
|
100
|
+
OPCInuse: 262159,
|
|
101
|
+
OPCInvalidConfig: 3221487632,
|
|
102
|
+
OPCNotFound: 3221487633,
|
|
103
|
+
OPCInvalidPID: 3221488131
|
|
104
|
+
},
|
|
105
|
+
errorDesc: {
|
|
106
|
+
"3221487617": "The value of the handle is invalid",
|
|
107
|
+
"3221487620": "The server cannot convert the data between the specified format/requested data type and the canonical data type",
|
|
108
|
+
"3221487621": "The requested operation cannot be done on a public group",
|
|
109
|
+
"3221487622": "The Items AccessRights do not allow the operation",
|
|
110
|
+
"3221487623": "The item ID is not defined in the server address space (on add or validate) or no longer exists in the server address space (for read or write)",
|
|
111
|
+
"3221487624": "The item ID doesn't conform to the server's syntax",
|
|
112
|
+
"3221487625": "The filter string was not valid",
|
|
113
|
+
"3221487626": "The item's access path is not known to the server",
|
|
114
|
+
"3221487627": "The value was out of range",
|
|
115
|
+
"3221487628": "Duplicate name not allowed",
|
|
116
|
+
"262157": "The server does not support the requested data rate but will use the closest available rate",
|
|
117
|
+
"262158": "A value passed to WRITE was accepted but the output was clamped",
|
|
118
|
+
"262159": "The operation cannot be performed because the object is bering referenced",
|
|
119
|
+
"3221487632": "The server's configuration file is in an invalid format",
|
|
120
|
+
"3221487633": "Requested Object (e.g. a public group) was not found",
|
|
121
|
+
"3221488131": "The passed property ID is not valid for the item"
|
|
122
|
+
},
|
|
123
|
+
property: {
|
|
124
|
+
DATATYPE: 1,
|
|
125
|
+
VALUE: 2,
|
|
126
|
+
QUALITY: 3,
|
|
127
|
+
TIMESTAMP: 4,
|
|
128
|
+
ACCESS_RIGHTS: 5,
|
|
129
|
+
SCAN_RATE: 6,
|
|
130
|
+
EU_TYPE: 7,
|
|
131
|
+
EU_INFO: 8,
|
|
132
|
+
EU_UNITS: 100,
|
|
133
|
+
DESCRIPTION: 101,
|
|
134
|
+
HIGH_EU: 102,
|
|
135
|
+
LOW_EU: 103,
|
|
136
|
+
HIGH_IR: 104,
|
|
137
|
+
LOW_IR: 105,
|
|
138
|
+
CLOSE_LABEL: 106,
|
|
139
|
+
OPEN_LABEL: 107,
|
|
140
|
+
TIMEZONE: 108,
|
|
141
|
+
CONDITION_STATUS: 300,
|
|
142
|
+
ALARM_QUICK_HELP: 301,
|
|
143
|
+
ALARM_AREA_LIST: 302,
|
|
144
|
+
PRIMARY_ALARM_AREA: 303,
|
|
145
|
+
CONDITION_LOGIC: 304,
|
|
146
|
+
LIMIT_EXCEEDED: 305,
|
|
147
|
+
DEADBAND: 306,
|
|
148
|
+
HIHI_LIMIT: 307,
|
|
149
|
+
HI_LIMIT: 308,
|
|
150
|
+
LO_LIMIT: 309,
|
|
151
|
+
LOLO_LIMIT: 310,
|
|
152
|
+
CHANGE_RATE_LIMIT: 311,
|
|
153
|
+
DEVIATION_LIMIT: 312,
|
|
154
|
+
SOUND_FILE: 313,
|
|
155
|
+
TYPE_SYSTEM_ID: 600,
|
|
156
|
+
DICTIONARY_ID: 601,
|
|
157
|
+
TYPE_ID: 602,
|
|
158
|
+
DICTIONARY: 603,
|
|
159
|
+
TYPE_DESCRIPTION: 604,
|
|
160
|
+
CONSISTENCY_WINDOW: 605,
|
|
161
|
+
WRITE_BEHAVIOR: 606,
|
|
162
|
+
UNCONVERTED_ITEM_ID: 607,
|
|
163
|
+
UNFILTERED_ITEM_ID: 608,
|
|
164
|
+
DATA_FILTER_VALUE: 609,
|
|
165
|
+
},
|
|
166
|
+
propertyDesc: {
|
|
167
|
+
"1": "Item Canonical Data Type",
|
|
168
|
+
"2": "Item Value",
|
|
169
|
+
"3": "Item Quality",
|
|
170
|
+
"4": "Item Timestamp",
|
|
171
|
+
"5": "Item Access Rights",
|
|
172
|
+
"6": "Server Scan Rate",
|
|
173
|
+
"7": "Item EU Type",
|
|
174
|
+
"8": "Item EU Info",
|
|
175
|
+
"100": "EU Units",
|
|
176
|
+
"101": "Item Description",
|
|
177
|
+
"102": "High EU",
|
|
178
|
+
"103": "Low EU",
|
|
179
|
+
"104": "High Instrument Range",
|
|
180
|
+
"105": "Low Instrument Range",
|
|
181
|
+
"106": "Contact Close Label",
|
|
182
|
+
"107": "Contact Open Label",
|
|
183
|
+
"108": "Item Timezone",
|
|
184
|
+
"300": "Condition Status",
|
|
185
|
+
"301": "Alarm Quick Help",
|
|
186
|
+
"302": "Alarm Area List",
|
|
187
|
+
"303": "Primary Alarm Area",
|
|
188
|
+
"304": "Condition Logic",
|
|
189
|
+
"305": "Limit Exceeded",
|
|
190
|
+
"306": "Deadband",
|
|
191
|
+
"307": "HiHi Limit",
|
|
192
|
+
"308": "Hi Limit",
|
|
193
|
+
"309": "Lo Limit",
|
|
194
|
+
"310": "LoLo Limit",
|
|
195
|
+
"311": "Rate of Change Limit",
|
|
196
|
+
"312": "Deviation Limit",
|
|
197
|
+
"313": "Sound File",
|
|
198
|
+
"600": "Type System ID",
|
|
199
|
+
"601": "Dictionary ID",
|
|
200
|
+
"602": "Type ID",
|
|
201
|
+
"603": "Dictionary",
|
|
202
|
+
"604": "Type Description",
|
|
203
|
+
"605": "Consistency Window",
|
|
204
|
+
"606": "Write Behavior",
|
|
205
|
+
"607": "Unconverted Item ID",
|
|
206
|
+
"608": "Unfiltered Item ID",
|
|
207
|
+
"609": "Data Filter Value"
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
module.exports = Object.freeze(constants);
|
|
@@ -0,0 +1,161 @@
|
|
|
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 dcom = require('node-dcom');
|
|
9
|
+
const util = require('util');
|
|
10
|
+
const debug = util.debuglog('node-opc-da');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Represents an EnumString
|
|
14
|
+
*/
|
|
15
|
+
class EnumString {
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
* @param {number} [batchSize=10]
|
|
20
|
+
*/
|
|
21
|
+
constructor(batchSize){
|
|
22
|
+
this._batchSize = batchSize || 10;
|
|
23
|
+
|
|
24
|
+
this._comObj = null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param {*} unknown
|
|
30
|
+
* @returns {Promise<?>}
|
|
31
|
+
*/
|
|
32
|
+
async init(unknown) {
|
|
33
|
+
debug("Initing EnumString...");
|
|
34
|
+
if (this._comObj) throw new Error("Already initialized");
|
|
35
|
+
|
|
36
|
+
this._comObj = await unknown.queryInterface(constants.iid.IEnumString_IID);
|
|
37
|
+
debug("EnumString successfully inited.");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async end(hresult) {
|
|
41
|
+
debug("Destroying EnumString...");
|
|
42
|
+
if (!this._comObj) return;
|
|
43
|
+
|
|
44
|
+
let obj = this._comObj;
|
|
45
|
+
debug(String(new Error(String(hresult))));
|
|
46
|
+
this._comObj = null;
|
|
47
|
+
await obj.release();
|
|
48
|
+
debug("EnumString successfully destroyed.");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @param {number} num
|
|
54
|
+
* @returns {Promise<string[]>}
|
|
55
|
+
* @opNum 0
|
|
56
|
+
*/
|
|
57
|
+
async next(num) {
|
|
58
|
+
debug("Querying the server for a batch of " + num + " items...");
|
|
59
|
+
if (!this._comObj) throw new Error("Not initialized");
|
|
60
|
+
|
|
61
|
+
if (num <= 0) return [];
|
|
62
|
+
|
|
63
|
+
let callObject = new dcom.CallBuilder(true);
|
|
64
|
+
callObject.setOpnum(0);
|
|
65
|
+
|
|
66
|
+
let strValue = new dcom.ComValue(new dcom.ComString(dcom.Flags.FLAG_REPRESENTATION_STRING_LPWSTR), dcom.Types.COMSTRING);
|
|
67
|
+
let strArrayValue = new dcom.ComValue(new dcom.ComArray(strValue, null, 1, true, true), dcom.Types.COMARRAY);
|
|
68
|
+
callObject.addInParamAsInt(num, dcom.Flags.FLAG_NULL);
|
|
69
|
+
callObject.addOutParamAsObject(strArrayValue, dcom.Flags.FLAG_NULL);
|
|
70
|
+
callObject.addOutParamAsType(dcom.Types.INTEGER, dcom.Flags.FLAG_NULL);
|
|
71
|
+
|
|
72
|
+
let resultObj = await this._comObj.call(callObject);
|
|
73
|
+
|
|
74
|
+
let hresult = resultObj.hresult;
|
|
75
|
+
let result = resultObj.getResults();
|
|
76
|
+
if (hresult != 0) {
|
|
77
|
+
if (result.lenght == 0)
|
|
78
|
+
throw new Error(String(hresult));
|
|
79
|
+
else
|
|
80
|
+
debug("No more items.");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let resultData;
|
|
84
|
+
if (result instanceof dcom.ComValue)
|
|
85
|
+
resultData = result[0].getValue().getArrayInstance();
|
|
86
|
+
else
|
|
87
|
+
resultData = result[0].getValue().getArrayInstance();
|
|
88
|
+
let count = result[1].getValue();
|
|
89
|
+
|
|
90
|
+
let res = [];
|
|
91
|
+
for (let i = 0; i < count; i++) {
|
|
92
|
+
res.push(resultData[i].getValue().getString());
|
|
93
|
+
}
|
|
94
|
+
debug("Items successfullly obtained.");
|
|
95
|
+
return res;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
*
|
|
100
|
+
* @param {number} num
|
|
101
|
+
* @returns {Promise<>}
|
|
102
|
+
* @opnum 1
|
|
103
|
+
*/
|
|
104
|
+
async skip(num) {
|
|
105
|
+
if (!this._comObj) throw new Error("Not initialized");
|
|
106
|
+
|
|
107
|
+
if (num <= 0) return [];
|
|
108
|
+
|
|
109
|
+
let callObject = new dcom.CallBuilder(true);
|
|
110
|
+
callObject.setOpnum(1);
|
|
111
|
+
|
|
112
|
+
callObject.addInParamAsInt(num, dcom.Flags.FLAG_NULL);
|
|
113
|
+
|
|
114
|
+
await this._comObj.call(callObject)
|
|
115
|
+
.catch(function(reject) {
|
|
116
|
+
throw reject;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
*
|
|
122
|
+
* @returns {Promise<>}
|
|
123
|
+
* @opnum 2
|
|
124
|
+
*/
|
|
125
|
+
async reset() {
|
|
126
|
+
debug("Reseting EnumString...");
|
|
127
|
+
if (!this._comObj) throw new Error("Not initialized");
|
|
128
|
+
|
|
129
|
+
let callObject = new dcom.CallBuilder(true);
|
|
130
|
+
callObject.setOpnum(2);
|
|
131
|
+
|
|
132
|
+
await this._comObj.call(callObject)
|
|
133
|
+
.catch(function(reject) {
|
|
134
|
+
throw reject;
|
|
135
|
+
});
|
|
136
|
+
debug("EnumString successfully reseted.");
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ------
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @returns {Promise<string[]>}
|
|
143
|
+
*/
|
|
144
|
+
async asArray(){
|
|
145
|
+
debug("Creating an Array for the current EnumString...");
|
|
146
|
+
await this.reset();
|
|
147
|
+
let part, res = [];
|
|
148
|
+
do {
|
|
149
|
+
part = await this.next(this._batchSize)
|
|
150
|
+
.catch(function(reject) {
|
|
151
|
+
throw reject;
|
|
152
|
+
});
|
|
153
|
+
res.push(...part);
|
|
154
|
+
} while (part.length == this._batchSize);
|
|
155
|
+
|
|
156
|
+
debug("Array of EnumString itens sucessfully created.");
|
|
157
|
+
return res;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
module.exports = EnumString;
|
package/src/filetime.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
//@ts-check
|
|
2
|
+
|
|
3
|
+
const {Struct} = require('node-dcom');
|
|
4
|
+
const Long = require('long');
|
|
5
|
+
|
|
6
|
+
class FileTime {
|
|
7
|
+
|
|
8
|
+
constructor(hi, lo){
|
|
9
|
+
this._hi = hi;
|
|
10
|
+
this._lo = lo;
|
|
11
|
+
this._date = null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get hi(){
|
|
15
|
+
return this._hi;
|
|
16
|
+
}
|
|
17
|
+
get lo(){
|
|
18
|
+
return this._lo;
|
|
19
|
+
}
|
|
20
|
+
set hi(hi){
|
|
21
|
+
this._hi = hi;
|
|
22
|
+
this._date = null;
|
|
23
|
+
}
|
|
24
|
+
set lo(lo){
|
|
25
|
+
this._lo = lo;
|
|
26
|
+
this._date = null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @returns {Date}
|
|
31
|
+
*/
|
|
32
|
+
getDate() {
|
|
33
|
+
if (!this._date) this._computeDate();
|
|
34
|
+
return this._date;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
_computeDate(){
|
|
38
|
+
let ulong = new Long(this._lo, this._hi, true).div(10000);
|
|
39
|
+
let epochBase = ulong.sub(11644473600000);
|
|
40
|
+
|
|
41
|
+
if (epochBase.greaterThan(ulong))
|
|
42
|
+
epochBase = epochBase.toSigned();
|
|
43
|
+
else
|
|
44
|
+
epochBase = epochBase.toNumber();
|
|
45
|
+
|
|
46
|
+
this._date = new Date(epochBase);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
toString(){
|
|
50
|
+
return `FileTime[${this._hi && this._lo ? this.getDate() : 'null'}]`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @returns {Struct}
|
|
56
|
+
*/
|
|
57
|
+
function getStruct(){
|
|
58
|
+
let struct = new Struct();
|
|
59
|
+
struct.addMember(0); //lo
|
|
60
|
+
struct.addMember(0); //hi
|
|
61
|
+
|
|
62
|
+
return struct;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
* @param {Struct} struct
|
|
68
|
+
* @returns {FileTime}
|
|
69
|
+
*/
|
|
70
|
+
function fromStruct(struct){
|
|
71
|
+
let lo = struct.getMember(0).getValue();
|
|
72
|
+
let hi = struct.getMember(1).getValue();
|
|
73
|
+
|
|
74
|
+
return new FileTime(hi, lo);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = {
|
|
78
|
+
FileTime, getStruct, fromStruct
|
|
79
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
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');
|
|
8
|
+
const OPCAsyncIO = require('./opcAsyncIO');
|
|
9
|
+
const OPCBrowser = require('./opcBrowser');
|
|
10
|
+
const OPCCommon = require('./opcCommon');
|
|
11
|
+
const OPCGroupStateManager = require('./opcGroupStateManager');
|
|
12
|
+
const OPCItemIO = require('./opcItemIO');
|
|
13
|
+
const OPCItemManager = require('./opcItemManager');
|
|
14
|
+
const OPCItemProperties = require('./opcItemProperties');
|
|
15
|
+
const OPCServer = require('./opcServer');
|
|
16
|
+
const OPCSyncIO = require('./opcSyncIO');
|
|
17
|
+
const dcom = require('node-dcom');
|
|
18
|
+
const EventEmitter = require('events').EventEmitter;
|
|
19
|
+
const {ComServer, Session, Clsid} = dcom;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
* @param {String} address
|
|
24
|
+
* @param {String} domain
|
|
25
|
+
* @param {String} user
|
|
26
|
+
* @param {String} pass
|
|
27
|
+
* @param {String} clsid
|
|
28
|
+
* @param {object} [opts]
|
|
29
|
+
* @returns {Promise<{comServer:ComServer, opcServer:OPCServer}>}
|
|
30
|
+
*/
|
|
31
|
+
async function createServer(address, domain, user, pass, clsid, opts) {
|
|
32
|
+
EventEmitter.call(this);
|
|
33
|
+
let session = new Session();
|
|
34
|
+
session = session.createSession(domain, user, pass);
|
|
35
|
+
session.setGlobalSocketTimeout(7000);
|
|
36
|
+
|
|
37
|
+
let comServer = new ComServer(new Clsid(clsid), address, session);
|
|
38
|
+
|
|
39
|
+
await comServer.init();
|
|
40
|
+
console.log(`debug`);
|
|
41
|
+
let comObject = await comServer.createInstance();
|
|
42
|
+
|
|
43
|
+
let opcServer = new OPCServer(opts);
|
|
44
|
+
await opcServer.init(comObject);
|
|
45
|
+
|
|
46
|
+
return {comServer, opcServer};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = {
|
|
50
|
+
constants,
|
|
51
|
+
OPCAsyncIO,
|
|
52
|
+
OPCBrowser,
|
|
53
|
+
OPCCommon,
|
|
54
|
+
OPCGroupStateManager,
|
|
55
|
+
OPCItemIO,
|
|
56
|
+
OPCItemManager,
|
|
57
|
+
OPCItemProperties,
|
|
58
|
+
OPCServer,
|
|
59
|
+
OPCSyncIO,
|
|
60
|
+
dcom,
|
|
61
|
+
createServer
|
|
62
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
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 Sync IO Object
|
|
11
|
+
*/
|
|
12
|
+
class OPCAsyncIO {
|
|
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.IOPCAsyncIO2_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[]} handles array of server handles
|
|
40
|
+
* @returns {Promise<object>}
|
|
41
|
+
* @opNum 0
|
|
42
|
+
*/
|
|
43
|
+
async read(handles) {
|
|
44
|
+
if (!this._comObj) throw new Error("Not initialized");
|
|
45
|
+
|
|
46
|
+
//should return auto generated transaction id and cancel id
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** ??? */
|
|
50
|
+
async write() {
|
|
51
|
+
if (!this._comObj) throw new Error("Not initialized");
|
|
52
|
+
|
|
53
|
+
throw new Error("Not Implemented");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @param {number} transactionID
|
|
59
|
+
* @param {number} source
|
|
60
|
+
* @returns {Promise<number>}
|
|
61
|
+
* @opNum 2
|
|
62
|
+
*/
|
|
63
|
+
async refresh(transactionID, source) {
|
|
64
|
+
if (!this._comObj) throw new Error("Not initialized");
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
*
|
|
70
|
+
* @param {number} cancelID
|
|
71
|
+
* @returns {Promise<void>}
|
|
72
|
+
* @opNum 3
|
|
73
|
+
*/
|
|
74
|
+
async cancel(cancelID) {
|
|
75
|
+
if (!this._comObj) throw new Error("Not initialized");
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* @param {boolean} state
|
|
82
|
+
* @returns {Promise<void>}
|
|
83
|
+
* @opNum 4
|
|
84
|
+
*/
|
|
85
|
+
async setEnable(state) {
|
|
86
|
+
if (!this._comObj) throw new Error("Not initialized");
|
|
87
|
+
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
*
|
|
92
|
+
* @returns {Promise<boolean>}
|
|
93
|
+
* @opNum 5
|
|
94
|
+
*/
|
|
95
|
+
async getEnable() {
|
|
96
|
+
if (!this._comObj) throw new Error("Not initialized");
|
|
97
|
+
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = OPCAsyncIO;
|