node-opcua-server 2.59.0 → 2.60.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-opcua-server",
3
- "version": "2.59.0",
3
+ "version": "2.60.0",
4
4
  "description": "pure nodejs OPCUA SDK - module -server",
5
5
  "scripts": {
6
6
  "build": "tsc -b",
@@ -14,61 +14,61 @@
14
14
  "dependencies": {
15
15
  "@ster5/global-mutex": "^1.1.1",
16
16
  "@types/underscore": "^1.11.3",
17
- "async": "^3.2.1",
17
+ "async": "^3.2.2",
18
18
  "bonjour": "^3.5.0",
19
19
  "browser-process-hrtime": "^1.0.0",
20
20
  "dequeue": "^1.0.5",
21
21
  "lodash": "4.17.21",
22
- "node-opcua-address-space": "2.59.0",
22
+ "node-opcua-address-space": "2.60.0",
23
23
  "node-opcua-assert": "2.55.0",
24
- "node-opcua-basic-types": "2.57.0",
25
- "node-opcua-certificate-manager": "2.57.0",
26
- "node-opcua-client": "2.59.0",
27
- "node-opcua-client-dynamic-extension-object": "2.59.0",
28
- "node-opcua-common": "2.59.0",
24
+ "node-opcua-basic-types": "2.60.0",
25
+ "node-opcua-certificate-manager": "2.60.0",
26
+ "node-opcua-client": "2.60.0",
27
+ "node-opcua-client-dynamic-extension-object": "2.60.0",
28
+ "node-opcua-common": "2.60.0",
29
29
  "node-opcua-constants": "2.52.0",
30
30
  "node-opcua-crypto": "^1.7.4",
31
- "node-opcua-data-model": "2.57.0",
32
- "node-opcua-data-value": "2.59.0",
33
- "node-opcua-date-time": "2.55.0",
34
- "node-opcua-debug": "2.55.0",
31
+ "node-opcua-data-model": "2.60.0",
32
+ "node-opcua-data-value": "2.60.0",
33
+ "node-opcua-date-time": "2.60.0",
34
+ "node-opcua-debug": "2.60.0",
35
35
  "node-opcua-enum": "2.55.0",
36
- "node-opcua-extension-object": "2.57.0",
37
- "node-opcua-factory": "2.57.0",
36
+ "node-opcua-extension-object": "2.60.0",
37
+ "node-opcua-factory": "2.60.0",
38
38
  "node-opcua-hostname": "2.55.0",
39
- "node-opcua-nodeid": "2.55.0",
39
+ "node-opcua-nodeid": "2.60.0",
40
40
  "node-opcua-nodesets": "2.57.0",
41
- "node-opcua-numeric-range": "2.57.0",
42
- "node-opcua-object-registry": "2.56.0",
43
- "node-opcua-pki": "^2.12.0",
44
- "node-opcua-secure-channel": "2.59.0",
45
- "node-opcua-service-browse": "2.59.0",
46
- "node-opcua-service-call": "2.59.0",
47
- "node-opcua-service-discovery": "2.59.0",
48
- "node-opcua-service-endpoints": "2.59.0",
49
- "node-opcua-service-filter": "2.59.0",
50
- "node-opcua-service-history": "2.59.0",
51
- "node-opcua-service-node-management": "2.59.0",
52
- "node-opcua-service-query": "2.59.0",
53
- "node-opcua-service-read": "2.59.0",
54
- "node-opcua-service-register-node": "2.59.0",
55
- "node-opcua-service-secure-channel": "2.59.0",
56
- "node-opcua-service-session": "2.59.0",
57
- "node-opcua-service-subscription": "2.59.0",
58
- "node-opcua-service-translate-browse-path": "2.59.0",
59
- "node-opcua-service-write": "2.59.0",
41
+ "node-opcua-numeric-range": "2.60.0",
42
+ "node-opcua-object-registry": "2.60.0",
43
+ "node-opcua-pki": "^2.12.1",
44
+ "node-opcua-secure-channel": "2.60.0",
45
+ "node-opcua-service-browse": "2.60.0",
46
+ "node-opcua-service-call": "2.60.0",
47
+ "node-opcua-service-discovery": "2.60.0",
48
+ "node-opcua-service-endpoints": "2.60.0",
49
+ "node-opcua-service-filter": "2.60.0",
50
+ "node-opcua-service-history": "2.60.0",
51
+ "node-opcua-service-node-management": "2.60.0",
52
+ "node-opcua-service-query": "2.60.0",
53
+ "node-opcua-service-read": "2.60.0",
54
+ "node-opcua-service-register-node": "2.60.0",
55
+ "node-opcua-service-secure-channel": "2.60.0",
56
+ "node-opcua-service-session": "2.60.0",
57
+ "node-opcua-service-subscription": "2.60.0",
58
+ "node-opcua-service-translate-browse-path": "2.60.0",
59
+ "node-opcua-service-write": "2.60.0",
60
60
  "node-opcua-status-code": "2.56.0",
61
- "node-opcua-types": "2.59.0",
62
- "node-opcua-utils": "2.57.0",
63
- "node-opcua-variant": "2.59.0"
61
+ "node-opcua-types": "2.60.0",
62
+ "node-opcua-utils": "2.60.0",
63
+ "node-opcua-variant": "2.60.0"
64
64
  },
65
65
  "devDependencies": {
66
- "node-opcua-data-access": "2.59.0",
67
- "node-opcua-leak-detector": "2.56.0",
66
+ "node-opcua-data-access": "2.60.0",
67
+ "node-opcua-leak-detector": "2.60.0",
68
68
  "node-opcua-test-helpers": "2.42.0",
69
- "node-opcua-transport": "2.59.0",
69
+ "node-opcua-transport": "2.60.0",
70
70
  "should": "^13.2.3",
71
- "sinon": "^11.1.2"
71
+ "sinon": "^12.0.1"
72
72
  },
73
73
  "author": "Etienne Rossignon",
74
74
  "license": "MIT",
@@ -85,5 +85,5 @@
85
85
  "internet of things"
86
86
  ],
87
87
  "homepage": "http://node-opcua.github.io/",
88
- "gitHead": "ea10265745d3d4b8af249a4e13288ad71232706f"
88
+ "gitHead": "56dc8584b9118ee2f3bfb0b2e9d456b609ccbac8"
89
89
  }
@@ -1,8 +1,8 @@
1
1
  export interface ISocketData {
2
2
  bytesRead: number;
3
3
  bytesWritten: number;
4
- localAddress: string;
5
- localPort: number;
4
+ localAddress?: string;
5
+ localPort?: number;
6
6
  remoteAddress?: string;
7
7
  remoteFamily?: string;
8
8
  remotePort?: number;
@@ -1256,7 +1256,7 @@ export class OPCUAServer extends OPCUABaseServer {
1256
1256
  * ```
1257
1257
  * ```javascript
1258
1258
  * // shutdown within 10 seconds
1259
- * server.engine .shutdownReason = coerceLocalizedText("Shutdown for maintenance");
1259
+ * server.engine.shutdownReason = coerceLocalizedText("Shutdown for maintenance");
1260
1260
  * server.shutdown(10000,function(err) {
1261
1261
  * });
1262
1262
  * ```
@@ -2207,6 +2207,7 @@ export class OPCUAServer extends OPCUABaseServer {
2207
2207
  }
2208
2208
  return channel.send_response("MSG", response1, message);
2209
2209
  } catch (err) {
2210
+ // istanbul ignore next
2210
2211
  if (err instanceof Error) {
2211
2212
  // istanbul ignore next
2212
2213
  errorLog(
@@ -2630,7 +2631,6 @@ export class OPCUAServer extends OPCUABaseServer {
2630
2631
  // ask for a refresh of asynchronous variables
2631
2632
  this.engine.refreshValues(request.nodesToRead, request.maxAge, (err?: Error | null) => {
2632
2633
  assert(!err, " error not handled here , fix me");
2633
-
2634
2634
  results = this.engine.read(context, request);
2635
2635
 
2636
2636
  assert(results[0].schema.name === "DataValue");
@@ -229,8 +229,8 @@ function getMonitoredItemsId(
229
229
  const callMethodResult = new CallMethodResult({
230
230
  statusCode: result.statusCode,
231
231
  outputArguments: [
232
- { dataType: DataType.UInt32, arrayType: VariantArrayType.Array, value: new Uint32Array(result.serverHandles) },
233
- { dataType: DataType.UInt32, arrayType: VariantArrayType.Array, value: new Uint32Array(result.clientHandles) }
232
+ { dataType: DataType.UInt32, arrayType: VariantArrayType.Array, value: result.serverHandles },
233
+ { dataType: DataType.UInt32, arrayType: VariantArrayType.Array, value: result.clientHandles }
234
234
  ]
235
235
  });
236
236
  callback(null, callMethodResult);
@@ -473,8 +473,7 @@ export class ServerEngine extends EventEmitter {
473
473
  this._orphanPublishEngine.shutdown();
474
474
  }
475
475
 
476
- // xx console.log("xxxxxxxxx ServerEngine.shutdown must terminate "+ tokens.length," sessions");
477
-
476
+
478
477
  for (const token of tokens) {
479
478
  this.closeSession(token, true, "Terminated");
480
479
  }
@@ -642,7 +641,7 @@ export class ServerEngine extends EventEmitter {
642
641
  public setServerState(serverState: ServerState): void {
643
642
  assert(serverState !== null && serverState !== undefined);
644
643
  this.addressSpace?.rootFolder?.objects?.server?.serverStatus?.state?.setValueFromSource({
645
- dataType: DataType.UInt32,
644
+ dataType: DataType.Int32,
646
645
  value: serverState
647
646
  });
648
647
  }
@@ -817,8 +816,7 @@ export class ServerEngine extends EventEmitter {
817
816
 
818
817
  // TimeZoneDataType
819
818
  const timeZoneDataType = addressSpace.findDataType(resolveNodeId(DataTypeIds.TimeZoneDataType))!;
820
- // xx console.log(timeZoneDataType.toString());
821
-
819
+
822
820
  const timeZone = new TimeZoneDataType({
823
821
  daylightSavingInOffset: /* boolean*/ false,
824
822
  offset: /* int16 */ 0
@@ -1076,36 +1074,36 @@ export class ServerEngine extends EventEmitter {
1076
1074
  // mainly for compliance
1077
1075
 
1078
1076
  // The version number for the data type description. i=104
1079
- bindStandardScalar(VariableIds.DataTypeDescriptionType_DataTypeVersion, DataType.UInt16, () => {
1080
- return 0.0;
1077
+ bindStandardScalar(VariableIds.DataTypeDescriptionType_DataTypeVersion, DataType.String, () => {
1078
+ return "0";
1081
1079
  });
1082
1080
 
1083
1081
  const namingRuleDataTypeNode = addressSpace.findDataType(resolveNodeId(DataTypeIds.NamingRuleType))! as UADataType;
1084
- // xx console.log(nrt.toString());
1082
+
1085
1083
  if (namingRuleDataTypeNode) {
1086
1084
  const namingRuleType = (namingRuleDataTypeNode as any)._getEnumerationInfo().nameIndex; // getEnumeration("NamingRuleType");
1087
1085
  if (!namingRuleType) {
1088
1086
  throw new Error("Cannot find Enumeration definition for NamingRuleType");
1089
1087
  }
1090
1088
  // i=111
1091
- bindStandardScalar(VariableIds.ModellingRuleType_NamingRule, DataType.UInt16, () => {
1089
+ bindStandardScalar(VariableIds.ModellingRuleType_NamingRule, DataType.Int32, () => {
1092
1090
  return 0;
1093
1091
  });
1094
1092
 
1095
1093
  // i=112
1096
- bindStandardScalar(VariableIds.ModellingRule_Mandatory_NamingRule, DataType.UInt16, () => {
1094
+ bindStandardScalar(VariableIds.ModellingRule_Mandatory_NamingRule, DataType.Int32, () => {
1097
1095
  return namingRuleType.Mandatory ? namingRuleType.Mandatory.value : 0;
1098
1096
  });
1099
1097
 
1100
1098
  // i=113
1101
- bindStandardScalar(VariableIds.ModellingRule_Optional_NamingRule, DataType.UInt16, () => {
1099
+ bindStandardScalar(VariableIds.ModellingRule_Optional_NamingRule, DataType.Int32, () => {
1102
1100
  return namingRuleType.Optional ? namingRuleType.Optional.value : 0;
1103
1101
  });
1104
1102
  // i=114
1105
- bindStandardScalar(VariableIds.ModellingRule_ExposesItsArray_NamingRule, DataType.UInt16, () => {
1103
+ bindStandardScalar(VariableIds.ModellingRule_ExposesItsArray_NamingRule, DataType.Int32, () => {
1106
1104
  return namingRuleType.ExposesItsArray ? namingRuleType.ExposesItsArray.value : 0;
1107
1105
  });
1108
- bindStandardScalar(VariableIds.ModellingRule_MandatoryPlaceholder_NamingRule, DataType.UInt16, () => {
1106
+ bindStandardScalar(VariableIds.ModellingRule_MandatoryPlaceholder_NamingRule, DataType.Int32, () => {
1109
1107
  return namingRuleType.MandatoryPlaceholder ? namingRuleType.MandatoryPlaceholder.value : 0;
1110
1108
  });
1111
1109
  }
@@ -1162,7 +1160,6 @@ export class ServerEngine extends EventEmitter {
1162
1160
  if (samplingIntervalDiagnosticsArray) {
1163
1161
  addressSpace.deleteNode(samplingIntervalDiagnosticsArray);
1164
1162
  const s = serverDiagnosticsNode.getComponents();
1165
- // xx console.log(s.map((x) => x.browseName.toString()).join(" "));
1166
1163
  }
1167
1164
 
1168
1165
  const subscriptionDiagnosticsArrayNode = serverDiagnosticsNode.getComponentByName(
@@ -1233,9 +1230,9 @@ export class ServerEngine extends EventEmitter {
1233
1230
  node.onFirstBrowseAction = undefined;
1234
1231
  } catch (err) {
1235
1232
  if (err instanceof Error) {
1236
- console.log("onFirstBrowseAction method has failed", err.message);
1233
+ errorLog("onFirstBrowseAction method has failed", err.message);
1237
1234
  }
1238
- console.log(err);
1235
+ errorLog(err);
1239
1236
  }
1240
1237
  assert(node.onFirstBrowseAction === undefined, "expansion can only be made once");
1241
1238
  }
@@ -1720,7 +1717,6 @@ export class ServerEngine extends EventEmitter {
1720
1717
  }
1721
1718
  const subscription = session.publishEngine.getSubscriptionById(subscriptionId);
1722
1719
  if (subscription) {
1723
- // xx console.log("foundSubscription ", subscriptionId, " in session", session.sessionName);
1724
1720
  subscriptions.push(subscription);
1725
1721
  }
1726
1722
  });
@@ -1880,7 +1876,7 @@ export class ServerEngine extends EventEmitter {
1880
1876
  const referenceTime = new Date(Date.now() - maxAge);
1881
1877
 
1882
1878
  assert(callback instanceof Function);
1883
- const objectMap: any = {};
1879
+ const objectMap: Record<string, BaseNode> = {};
1884
1880
  for (const nodeToRefresh of nodesToRefresh) {
1885
1881
  // only consider node for which the caller wants to read the Value attribute
1886
1882
  // assuming that Value is requested if attributeId is missing,
@@ -1903,13 +1899,15 @@ export class ServerEngine extends EventEmitter {
1903
1899
 
1904
1900
  objectMap[key] = obj;
1905
1901
  }
1906
- if (Object.keys(objectMap).length === 0) {
1902
+
1903
+ const objectArray = Object.values(objectMap);
1904
+ if (objectArray.length === 0) {
1907
1905
  // nothing to do
1908
1906
  return callback(null, []);
1909
1907
  }
1910
1908
  // perform all asyncRefresh in parallel
1911
1909
  async.map(
1912
- objectMap,
1910
+ objectArray,
1913
1911
  (obj: BaseNode, inner_callback: DataValueCallback) => {
1914
1912
  if (obj.nodeClass !== NodeClass.Variable) {
1915
1913
  inner_callback(
@@ -1920,7 +1918,19 @@ export class ServerEngine extends EventEmitter {
1920
1918
  );
1921
1919
  return;
1922
1920
  }
1923
- (obj as UAVariable).asyncRefresh(referenceTime, inner_callback);
1921
+ try {
1922
+ (obj as UAVariable).asyncRefresh(referenceTime, (err, dataValue) => {
1923
+ inner_callback(err, dataValue);
1924
+ });
1925
+ } catch (err) {
1926
+
1927
+ // istanbul ignore next
1928
+ if (!(err instanceof Error)) {
1929
+ throw new Error("internal error");
1930
+ }
1931
+ errorLog("asyncRefresh internal error", err);
1932
+ inner_callback(err);
1933
+ }
1924
1934
  },
1925
1935
  (err?: Error | null, arrResult?: (DataValue | undefined)[]) => {
1926
1936
  callback(err || null, arrResult as DataValue[]);
@@ -2087,7 +2097,7 @@ export class ServerEngine extends EventEmitter {
2087
2097
  "HistoryReadDetails " +
2088
2098
  historyReadDetails.toString();
2089
2099
  if (doDebug) {
2090
- console.log(chalk.cyan("ServerEngine#_historyReadSingleNode "), chalk.white.bold(msg));
2100
+ debugLog(chalk.cyan("ServerEngine#_historyReadSingleNode "), chalk.white.bold(msg));
2091
2101
  }
2092
2102
  const err = new Error(msg);
2093
2103
  // object has no historyRead method
@@ -2132,13 +2142,12 @@ export class ServerEngine extends EventEmitter {
2132
2142
  if (methodNode && methodNode.bindMethod) {
2133
2143
  methodNode.bindMethod(func);
2134
2144
  } else {
2135
- console.log(
2145
+ warningLog(
2136
2146
  chalk.yellow("WARNING: cannot bind a method with id ") +
2137
2147
  chalk.cyan(nodeId.toString()) +
2138
2148
  chalk.yellow(". please check your nodeset.xml file or add this node programmatically")
2139
2149
  );
2140
-
2141
- console.log(traceFromThisProjectOnly());
2150
+ warningLog(traceFromThisProjectOnly());
2142
2151
  }
2143
2152
  }
2144
2153
 
@@ -196,7 +196,7 @@ export class ServerSession extends EventEmitter implements ISubscriber, ISession
196
196
  assert(!this.sessionObject, " sessionObject has not been cleared !");
197
197
 
198
198
  this.parent = null as any as ServerEngine;
199
- this.authenticationToken = NodeId.nullNodeId;
199
+ this.authenticationToken = new NodeId();
200
200
 
201
201
  if (this.publishEngine) {
202
202
  this.publishEngine.dispose();
@@ -407,12 +407,12 @@ export interface GetMonitoredItemsResult {
407
407
  * array of serverHandles for all MonitoredItems of the subscription
408
408
  * identified by subscriptionId.
409
409
  */
410
- serverHandles: number[];
410
+ serverHandles: Uint32Array;
411
411
  /**
412
412
  * array of clientHandles for all MonitoredItems of the subscription
413
413
  * identified by subscriptionId.
414
414
  */
415
- clientHandles: number[];
415
+ clientHandles: Uint32Array;
416
416
  statusCode: StatusCode;
417
417
  }
418
418
 
@@ -790,7 +790,7 @@ export class Subscription extends EventEmitter {
790
790
  this._pending_notifications.clear();
791
791
  this._sent_notification_messages = [];
792
792
 
793
- this.sessionId = NodeId.nullNodeId;
793
+ this.sessionId = new NodeId();
794
794
 
795
795
  this.$session = undefined;
796
796
  this.removeAllListeners();
@@ -1143,19 +1143,23 @@ export class Subscription extends EventEmitter {
1143
1143
  *
1144
1144
  */
1145
1145
  public getMonitoredItems(): GetMonitoredItemsResult {
1146
+ const monitoredItems = Object.keys(this.monitoredItems);
1147
+ const monitoredItemCount = monitoredItems.length;
1146
1148
  const result: GetMonitoredItemsResult = {
1147
- clientHandles: [] as number[],
1148
- serverHandles: [] as number[],
1149
+ clientHandles: new Uint32Array(monitoredItemCount),
1150
+ serverHandles: new Uint32Array(monitoredItemCount),
1149
1151
  statusCode: StatusCodes.Good
1150
1152
  };
1151
- for (const monitoredItemId of Object.keys(this.monitoredItems)) {
1152
- const monitoredItem = this.getMonitoredItem(parseInt(monitoredItemId, 10))!;
1153
- result.clientHandles.push(monitoredItem.clientHandle!);
1153
+ for (let index = 0; index < monitoredItemCount; index++) {
1154
+ const monitoredItemId = monitoredItems[index];
1155
+ const serverHandle = parseInt(monitoredItemId, 10);
1156
+ const monitoredItem = this.getMonitoredItem(serverHandle)!;
1157
+ result.clientHandles[index] = monitoredItem.clientHandle;
1154
1158
  // TODO: serverHandle is defined anywhere in the OPCUA Specification 1.02
1155
1159
  // I am not sure what shall be reported for serverHandle...
1156
1160
  // using monitoredItem.monitoredItemId instead...
1157
1161
  // May be a clarification in the OPCUA Spec is required.
1158
- result.serverHandles.push(parseInt(monitoredItemId, 10));
1162
+ result.serverHandles[index] = serverHandle;
1159
1163
  }
1160
1164
  return result;
1161
1165
  }