node-opcua-server 2.58.0 → 2.62.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/dist/i_socket_data.d.ts +2 -2
- package/dist/opcua_server.d.ts +2 -2
- package/dist/opcua_server.js +5 -1
- package/dist/opcua_server.js.map +1 -1
- package/dist/register_server_manager.js +5 -2
- package/dist/register_server_manager.js.map +1 -1
- package/dist/server_end_point.js +23 -46
- package/dist/server_end_point.js.map +1 -1
- package/dist/server_engine.js +31 -23
- package/dist/server_engine.js.map +1 -1
- package/dist/server_session.js +1 -1
- package/dist/server_session.js.map +1 -1
- package/dist/server_subscription.d.ts +2 -2
- package/dist/server_subscription.js +11 -7
- package/dist/server_subscription.js.map +1 -1
- package/package.json +42 -42
- package/source/i_socket_data.ts +2 -2
- package/source/opcua_server.ts +7 -4
- package/source/register_server_manager.ts +5 -2
- package/source/server_end_point.ts +27 -56
- package/source/server_engine.ts +34 -28
- package/source/server_session.ts +1 -1
- package/source/server_subscription.ts +13 -9
|
@@ -21,7 +21,8 @@ import {
|
|
|
21
21
|
ServerSecureChannelParent,
|
|
22
22
|
toURI,
|
|
23
23
|
AsymmetricAlgorithmSecurityHeader,
|
|
24
|
-
IServerSessionBase
|
|
24
|
+
IServerSessionBase,
|
|
25
|
+
Message
|
|
25
26
|
} from "node-opcua-secure-channel";
|
|
26
27
|
import { UserTokenType } from "node-opcua-service-endpoints";
|
|
27
28
|
import { EndpointDescription } from "node-opcua-service-endpoints";
|
|
@@ -747,7 +748,7 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
747
748
|
}
|
|
748
749
|
});
|
|
749
750
|
|
|
750
|
-
channel.on("message", (message:
|
|
751
|
+
channel.on("message", (message: Message) => {
|
|
751
752
|
// forward
|
|
752
753
|
this.emit("message", message, channel, this);
|
|
753
754
|
});
|
|
@@ -1001,10 +1002,12 @@ function estimateSecurityLevel(securityMode: MessageSecurityMode, securityPolicy
|
|
|
1001
1002
|
return 4; // deprecated => low
|
|
1002
1003
|
case SecurityPolicy.Basic256Rsa15:
|
|
1003
1004
|
return 4 + offset;
|
|
1005
|
+
case SecurityPolicy.Aes128_Sha256_RsaOaep:
|
|
1006
|
+
return 5 + offset;
|
|
1004
1007
|
case SecurityPolicy.Basic256Sha256:
|
|
1005
1008
|
return 6 + offset;
|
|
1006
|
-
case SecurityPolicy.
|
|
1007
|
-
return
|
|
1009
|
+
case SecurityPolicy.Aes256_Sha256_RsaPss:
|
|
1010
|
+
return 7 + offset;
|
|
1008
1011
|
|
|
1009
1012
|
default:
|
|
1010
1013
|
case SecurityPolicy.None:
|
|
@@ -1047,65 +1050,31 @@ function _makeEndpointDescription(options: MakeEndpointDescriptionOptions): Endp
|
|
|
1047
1050
|
});
|
|
1048
1051
|
}
|
|
1049
1052
|
|
|
1050
|
-
const
|
|
1051
|
-
options.
|
|
1052
|
-
|
|
1053
|
-
if (!onlyCertificateLessConnection) {
|
|
1054
|
-
if (options.securityPolicies.indexOf(SecurityPolicy.Basic256) >= 0) {
|
|
1053
|
+
const a = (tokenType: UserTokenType, securityPolicy: SecurityPolicy, name: string) => {
|
|
1054
|
+
if (options.securityPolicies.indexOf(securityPolicy) >= 0) {
|
|
1055
1055
|
userIdentityTokens.push({
|
|
1056
|
-
policyId: u(
|
|
1057
|
-
tokenType
|
|
1058
|
-
|
|
1056
|
+
policyId: u(name),
|
|
1057
|
+
tokenType,
|
|
1059
1058
|
issuedTokenType: null,
|
|
1060
1059
|
issuerEndpointUrl: null,
|
|
1061
|
-
securityPolicyUri:
|
|
1060
|
+
securityPolicyUri: securityPolicy
|
|
1062
1061
|
});
|
|
1063
1062
|
}
|
|
1063
|
+
};
|
|
1064
|
+
const onlyCertificateLessConnection =
|
|
1065
|
+
options.onlyCertificateLessConnection === undefined ? false : options.onlyCertificateLessConnection;
|
|
1064
1066
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
issuedTokenType: null,
|
|
1071
|
-
issuerEndpointUrl: null,
|
|
1072
|
-
securityPolicyUri: SecurityPolicy.Basic128Rsa15
|
|
1073
|
-
});
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
if (options.securityPolicies.indexOf(SecurityPolicy.Basic256Sha256) >= 0) {
|
|
1077
|
-
userIdentityTokens.push({
|
|
1078
|
-
policyId: u("username_basic256Sha256"),
|
|
1079
|
-
tokenType: UserTokenType.UserName,
|
|
1080
|
-
|
|
1081
|
-
issuedTokenType: null,
|
|
1082
|
-
issuerEndpointUrl: null,
|
|
1083
|
-
securityPolicyUri: SecurityPolicy.Basic256Sha256
|
|
1084
|
-
});
|
|
1085
|
-
}
|
|
1067
|
+
if (!onlyCertificateLessConnection) {
|
|
1068
|
+
a(UserTokenType.UserName, SecurityPolicy.Basic256, "username_basic256");
|
|
1069
|
+
a(UserTokenType.UserName, SecurityPolicy.Basic128Rsa15, "username_basic128Rsa15");
|
|
1070
|
+
a(UserTokenType.UserName, SecurityPolicy.Basic256Sha256, "username_basic256Sha256");
|
|
1071
|
+
a(UserTokenType.UserName, SecurityPolicy.Aes128_Sha256_RsaOaep, "username_aes128Sha256RsaOaep");
|
|
1086
1072
|
|
|
1087
1073
|
// X509
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
issuedTokenType: null,
|
|
1094
|
-
issuerEndpointUrl: null,
|
|
1095
|
-
securityPolicyUri: SecurityPolicy.Basic256
|
|
1096
|
-
});
|
|
1097
|
-
}
|
|
1098
|
-
// Certificate
|
|
1099
|
-
if (options.securityPolicies.indexOf(SecurityPolicy.Basic256Sha256) >= 0) {
|
|
1100
|
-
userIdentityTokens.push({
|
|
1101
|
-
policyId: u("certificate_basic256Sha256"),
|
|
1102
|
-
tokenType: UserTokenType.Certificate,
|
|
1103
|
-
|
|
1104
|
-
issuedTokenType: null,
|
|
1105
|
-
issuerEndpointUrl: null,
|
|
1106
|
-
securityPolicyUri: SecurityPolicy.Basic256Sha256
|
|
1107
|
-
});
|
|
1108
|
-
}
|
|
1074
|
+
a(UserTokenType.Certificate, SecurityPolicy.Basic256, "certificate_basic256");
|
|
1075
|
+
a(UserTokenType.Certificate, SecurityPolicy.Basic128Rsa15, "certificate_basic128Rsa15");
|
|
1076
|
+
a(UserTokenType.Certificate, SecurityPolicy.Basic256Sha256, "certificate_basic256Sha256");
|
|
1077
|
+
a(UserTokenType.Certificate, SecurityPolicy.Aes128_Sha256_RsaOaep, "certificate_aes128Sha256RsaOaep");
|
|
1109
1078
|
}
|
|
1110
1079
|
} else {
|
|
1111
1080
|
// note:
|
|
@@ -1195,5 +1164,7 @@ const defaultSecurityPolicies = [
|
|
|
1195
1164
|
SecurityPolicy.Basic128Rsa15,
|
|
1196
1165
|
SecurityPolicy.Basic256,
|
|
1197
1166
|
// xx UNUSED!! SecurityPolicy.Basic256Rsa15,
|
|
1198
|
-
SecurityPolicy.Basic256Sha256
|
|
1167
|
+
SecurityPolicy.Basic256Sha256,
|
|
1168
|
+
SecurityPolicy.Aes128_Sha256_RsaOaep
|
|
1169
|
+
// NO USED YET SecurityPolicy.Aes256_Sha256_RsaPss
|
|
1199
1170
|
];
|
package/source/server_engine.ts
CHANGED
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
AddressSpace,
|
|
12
12
|
BaseNode,
|
|
13
13
|
bindExtObjArrayNode,
|
|
14
|
-
DataValueCallback,
|
|
15
14
|
ensureDatatypeExtractedWithCallback,
|
|
16
15
|
ensureObjectIsSecure,
|
|
17
16
|
MethodFunctor,
|
|
@@ -229,8 +228,8 @@ function getMonitoredItemsId(
|
|
|
229
228
|
const callMethodResult = new CallMethodResult({
|
|
230
229
|
statusCode: result.statusCode,
|
|
231
230
|
outputArguments: [
|
|
232
|
-
{ dataType: DataType.UInt32, arrayType: VariantArrayType.Array, value:
|
|
233
|
-
{ dataType: DataType.UInt32, arrayType: VariantArrayType.Array, value:
|
|
231
|
+
{ dataType: DataType.UInt32, arrayType: VariantArrayType.Array, value: result.serverHandles },
|
|
232
|
+
{ dataType: DataType.UInt32, arrayType: VariantArrayType.Array, value: result.clientHandles }
|
|
234
233
|
]
|
|
235
234
|
});
|
|
236
235
|
callback(null, callMethodResult);
|
|
@@ -473,8 +472,6 @@ export class ServerEngine extends EventEmitter {
|
|
|
473
472
|
this._orphanPublishEngine.shutdown();
|
|
474
473
|
}
|
|
475
474
|
|
|
476
|
-
// xx console.log("xxxxxxxxx ServerEngine.shutdown must terminate "+ tokens.length," sessions");
|
|
477
|
-
|
|
478
475
|
for (const token of tokens) {
|
|
479
476
|
this.closeSession(token, true, "Terminated");
|
|
480
477
|
}
|
|
@@ -642,7 +639,7 @@ export class ServerEngine extends EventEmitter {
|
|
|
642
639
|
public setServerState(serverState: ServerState): void {
|
|
643
640
|
assert(serverState !== null && serverState !== undefined);
|
|
644
641
|
this.addressSpace?.rootFolder?.objects?.server?.serverStatus?.state?.setValueFromSource({
|
|
645
|
-
dataType: DataType.
|
|
642
|
+
dataType: DataType.Int32,
|
|
646
643
|
value: serverState
|
|
647
644
|
});
|
|
648
645
|
}
|
|
@@ -817,7 +814,6 @@ export class ServerEngine extends EventEmitter {
|
|
|
817
814
|
|
|
818
815
|
// TimeZoneDataType
|
|
819
816
|
const timeZoneDataType = addressSpace.findDataType(resolveNodeId(DataTypeIds.TimeZoneDataType))!;
|
|
820
|
-
// xx console.log(timeZoneDataType.toString());
|
|
821
817
|
|
|
822
818
|
const timeZone = new TimeZoneDataType({
|
|
823
819
|
daylightSavingInOffset: /* boolean*/ false,
|
|
@@ -1076,36 +1072,36 @@ export class ServerEngine extends EventEmitter {
|
|
|
1076
1072
|
// mainly for compliance
|
|
1077
1073
|
|
|
1078
1074
|
// The version number for the data type description. i=104
|
|
1079
|
-
bindStandardScalar(VariableIds.DataTypeDescriptionType_DataTypeVersion, DataType.
|
|
1080
|
-
return 0
|
|
1075
|
+
bindStandardScalar(VariableIds.DataTypeDescriptionType_DataTypeVersion, DataType.String, () => {
|
|
1076
|
+
return "0";
|
|
1081
1077
|
});
|
|
1082
1078
|
|
|
1083
1079
|
const namingRuleDataTypeNode = addressSpace.findDataType(resolveNodeId(DataTypeIds.NamingRuleType))! as UADataType;
|
|
1084
|
-
|
|
1080
|
+
|
|
1085
1081
|
if (namingRuleDataTypeNode) {
|
|
1086
1082
|
const namingRuleType = (namingRuleDataTypeNode as any)._getEnumerationInfo().nameIndex; // getEnumeration("NamingRuleType");
|
|
1087
1083
|
if (!namingRuleType) {
|
|
1088
1084
|
throw new Error("Cannot find Enumeration definition for NamingRuleType");
|
|
1089
1085
|
}
|
|
1090
1086
|
// i=111
|
|
1091
|
-
bindStandardScalar(VariableIds.ModellingRuleType_NamingRule, DataType.
|
|
1087
|
+
bindStandardScalar(VariableIds.ModellingRuleType_NamingRule, DataType.Int32, () => {
|
|
1092
1088
|
return 0;
|
|
1093
1089
|
});
|
|
1094
1090
|
|
|
1095
1091
|
// i=112
|
|
1096
|
-
bindStandardScalar(VariableIds.ModellingRule_Mandatory_NamingRule, DataType.
|
|
1092
|
+
bindStandardScalar(VariableIds.ModellingRule_Mandatory_NamingRule, DataType.Int32, () => {
|
|
1097
1093
|
return namingRuleType.Mandatory ? namingRuleType.Mandatory.value : 0;
|
|
1098
1094
|
});
|
|
1099
1095
|
|
|
1100
1096
|
// i=113
|
|
1101
|
-
bindStandardScalar(VariableIds.ModellingRule_Optional_NamingRule, DataType.
|
|
1097
|
+
bindStandardScalar(VariableIds.ModellingRule_Optional_NamingRule, DataType.Int32, () => {
|
|
1102
1098
|
return namingRuleType.Optional ? namingRuleType.Optional.value : 0;
|
|
1103
1099
|
});
|
|
1104
1100
|
// i=114
|
|
1105
|
-
bindStandardScalar(VariableIds.ModellingRule_ExposesItsArray_NamingRule, DataType.
|
|
1101
|
+
bindStandardScalar(VariableIds.ModellingRule_ExposesItsArray_NamingRule, DataType.Int32, () => {
|
|
1106
1102
|
return namingRuleType.ExposesItsArray ? namingRuleType.ExposesItsArray.value : 0;
|
|
1107
1103
|
});
|
|
1108
|
-
bindStandardScalar(VariableIds.ModellingRule_MandatoryPlaceholder_NamingRule, DataType.
|
|
1104
|
+
bindStandardScalar(VariableIds.ModellingRule_MandatoryPlaceholder_NamingRule, DataType.Int32, () => {
|
|
1109
1105
|
return namingRuleType.MandatoryPlaceholder ? namingRuleType.MandatoryPlaceholder.value : 0;
|
|
1110
1106
|
});
|
|
1111
1107
|
}
|
|
@@ -1162,7 +1158,6 @@ export class ServerEngine extends EventEmitter {
|
|
|
1162
1158
|
if (samplingIntervalDiagnosticsArray) {
|
|
1163
1159
|
addressSpace.deleteNode(samplingIntervalDiagnosticsArray);
|
|
1164
1160
|
const s = serverDiagnosticsNode.getComponents();
|
|
1165
|
-
// xx console.log(s.map((x) => x.browseName.toString()).join(" "));
|
|
1166
1161
|
}
|
|
1167
1162
|
|
|
1168
1163
|
const subscriptionDiagnosticsArrayNode = serverDiagnosticsNode.getComponentByName(
|
|
@@ -1233,9 +1228,9 @@ export class ServerEngine extends EventEmitter {
|
|
|
1233
1228
|
node.onFirstBrowseAction = undefined;
|
|
1234
1229
|
} catch (err) {
|
|
1235
1230
|
if (err instanceof Error) {
|
|
1236
|
-
|
|
1231
|
+
errorLog("onFirstBrowseAction method has failed", err.message);
|
|
1237
1232
|
}
|
|
1238
|
-
|
|
1233
|
+
errorLog(err);
|
|
1239
1234
|
}
|
|
1240
1235
|
assert(node.onFirstBrowseAction === undefined, "expansion can only be made once");
|
|
1241
1236
|
}
|
|
@@ -1720,7 +1715,6 @@ export class ServerEngine extends EventEmitter {
|
|
|
1720
1715
|
}
|
|
1721
1716
|
const subscription = session.publishEngine.getSubscriptionById(subscriptionId);
|
|
1722
1717
|
if (subscription) {
|
|
1723
|
-
// xx console.log("foundSubscription ", subscriptionId, " in session", session.sessionName);
|
|
1724
1718
|
subscriptions.push(subscription);
|
|
1725
1719
|
}
|
|
1726
1720
|
});
|
|
@@ -1880,7 +1874,7 @@ export class ServerEngine extends EventEmitter {
|
|
|
1880
1874
|
const referenceTime = new Date(Date.now() - maxAge);
|
|
1881
1875
|
|
|
1882
1876
|
assert(callback instanceof Function);
|
|
1883
|
-
const objectMap:
|
|
1877
|
+
const objectMap: Record<string, BaseNode> = {};
|
|
1884
1878
|
for (const nodeToRefresh of nodesToRefresh) {
|
|
1885
1879
|
// only consider node for which the caller wants to read the Value attribute
|
|
1886
1880
|
// assuming that Value is requested if attributeId is missing,
|
|
@@ -1903,14 +1897,16 @@ export class ServerEngine extends EventEmitter {
|
|
|
1903
1897
|
|
|
1904
1898
|
objectMap[key] = obj;
|
|
1905
1899
|
}
|
|
1906
|
-
|
|
1900
|
+
|
|
1901
|
+
const objectArray = Object.values(objectMap);
|
|
1902
|
+
if (objectArray.length === 0) {
|
|
1907
1903
|
// nothing to do
|
|
1908
1904
|
return callback(null, []);
|
|
1909
1905
|
}
|
|
1910
1906
|
// perform all asyncRefresh in parallel
|
|
1911
1907
|
async.map(
|
|
1912
|
-
|
|
1913
|
-
(obj: BaseNode, inner_callback:
|
|
1908
|
+
objectArray,
|
|
1909
|
+
(obj: BaseNode, inner_callback: CallbackT<DataValue>) => {
|
|
1914
1910
|
if (obj.nodeClass !== NodeClass.Variable) {
|
|
1915
1911
|
inner_callback(
|
|
1916
1912
|
null,
|
|
@@ -1920,7 +1916,18 @@ export class ServerEngine extends EventEmitter {
|
|
|
1920
1916
|
);
|
|
1921
1917
|
return;
|
|
1922
1918
|
}
|
|
1923
|
-
|
|
1919
|
+
try {
|
|
1920
|
+
(obj as UAVariable).asyncRefresh(referenceTime, (err, dataValue) => {
|
|
1921
|
+
inner_callback(err, dataValue);
|
|
1922
|
+
});
|
|
1923
|
+
} catch (err) {
|
|
1924
|
+
// istanbul ignore next
|
|
1925
|
+
if (!(err instanceof Error)) {
|
|
1926
|
+
throw new Error("internal error");
|
|
1927
|
+
}
|
|
1928
|
+
errorLog("asyncRefresh internal error", err);
|
|
1929
|
+
inner_callback(err);
|
|
1930
|
+
}
|
|
1924
1931
|
},
|
|
1925
1932
|
(err?: Error | null, arrResult?: (DataValue | undefined)[]) => {
|
|
1926
1933
|
callback(err || null, arrResult as DataValue[]);
|
|
@@ -2087,7 +2094,7 @@ export class ServerEngine extends EventEmitter {
|
|
|
2087
2094
|
"HistoryReadDetails " +
|
|
2088
2095
|
historyReadDetails.toString();
|
|
2089
2096
|
if (doDebug) {
|
|
2090
|
-
|
|
2097
|
+
debugLog(chalk.cyan("ServerEngine#_historyReadSingleNode "), chalk.white.bold(msg));
|
|
2091
2098
|
}
|
|
2092
2099
|
const err = new Error(msg);
|
|
2093
2100
|
// object has no historyRead method
|
|
@@ -2132,13 +2139,12 @@ export class ServerEngine extends EventEmitter {
|
|
|
2132
2139
|
if (methodNode && methodNode.bindMethod) {
|
|
2133
2140
|
methodNode.bindMethod(func);
|
|
2134
2141
|
} else {
|
|
2135
|
-
|
|
2142
|
+
warningLog(
|
|
2136
2143
|
chalk.yellow("WARNING: cannot bind a method with id ") +
|
|
2137
2144
|
chalk.cyan(nodeId.toString()) +
|
|
2138
2145
|
chalk.yellow(". please check your nodeset.xml file or add this node programmatically")
|
|
2139
2146
|
);
|
|
2140
|
-
|
|
2141
|
-
console.log(traceFromThisProjectOnly());
|
|
2147
|
+
warningLog(traceFromThisProjectOnly());
|
|
2142
2148
|
}
|
|
2143
2149
|
}
|
|
2144
2150
|
|
package/source/server_session.ts
CHANGED
|
@@ -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
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
1148
|
-
serverHandles:
|
|
1149
|
+
clientHandles: new Uint32Array(monitoredItemCount),
|
|
1150
|
+
serverHandles: new Uint32Array(monitoredItemCount),
|
|
1149
1151
|
statusCode: StatusCodes.Good
|
|
1150
1152
|
};
|
|
1151
|
-
for (
|
|
1152
|
-
const
|
|
1153
|
-
|
|
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
|
|
1162
|
+
result.serverHandles[index] = serverHandle;
|
|
1159
1163
|
}
|
|
1160
1164
|
return result;
|
|
1161
1165
|
}
|