node-opcua-server 2.81.0 → 2.83.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/base_server.js +10 -1
- package/dist/base_server.js.map +1 -1
- package/dist/monitored_item.d.ts +2 -3
- package/dist/monitored_item.js +69 -32
- package/dist/monitored_item.js.map +1 -1
- package/dist/node_sampler.js +4 -0
- package/dist/node_sampler.js.map +1 -1
- package/dist/opcua_server.js +1 -1
- package/dist/opcua_server.js.map +1 -1
- package/dist/server_end_point.d.ts +9 -7
- package/dist/server_end_point.js +82 -61
- package/dist/server_end_point.js.map +1 -1
- package/dist/server_engine.js +38 -21
- package/dist/server_engine.js.map +1 -1
- package/dist/server_subscription.js +5 -4
- package/dist/server_subscription.js.map +1 -1
- package/dist/validate_filter.js +26 -6
- package/dist/validate_filter.js.map +1 -1
- package/package.json +44 -44
- package/source/base_server.ts +15 -3
- package/source/monitored_item.ts +81 -44
- package/source/node_sampler.ts +6 -0
- package/source/opcua_server.ts +3 -4
- package/source/server_end_point.ts +116 -79
- package/source/server_engine.ts +62 -27
- package/source/server_subscription.ts +11 -8
- package/source/validate_filter.ts +28 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-opcua-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.83.0",
|
|
4
4
|
"description": "pure nodejs OPCUA SDK - module -server",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "tsc -b",
|
|
@@ -17,57 +17,57 @@
|
|
|
17
17
|
"chalk": "4.1.2",
|
|
18
18
|
"dequeue": "^1.0.5",
|
|
19
19
|
"lodash": "4.17.21",
|
|
20
|
-
"node-opcua-address-space": "2.
|
|
21
|
-
"node-opcua-address-space-base": "2.
|
|
20
|
+
"node-opcua-address-space": "2.83.0",
|
|
21
|
+
"node-opcua-address-space-base": "2.83.0",
|
|
22
22
|
"node-opcua-assert": "2.77.0",
|
|
23
|
-
"node-opcua-basic-types": "2.
|
|
24
|
-
"node-opcua-binary-stream": "2.
|
|
25
|
-
"node-opcua-certificate-manager": "2.
|
|
26
|
-
"node-opcua-client": "2.
|
|
27
|
-
"node-opcua-client-dynamic-extension-object": "2.
|
|
28
|
-
"node-opcua-common": "2.
|
|
23
|
+
"node-opcua-basic-types": "2.83.0",
|
|
24
|
+
"node-opcua-binary-stream": "2.83.0",
|
|
25
|
+
"node-opcua-certificate-manager": "2.83.0",
|
|
26
|
+
"node-opcua-client": "2.83.0",
|
|
27
|
+
"node-opcua-client-dynamic-extension-object": "2.83.0",
|
|
28
|
+
"node-opcua-common": "2.83.0",
|
|
29
29
|
"node-opcua-constants": "2.77.0",
|
|
30
|
-
"node-opcua-crypto": "^1.
|
|
31
|
-
"node-opcua-data-model": "2.
|
|
32
|
-
"node-opcua-data-value": "2.
|
|
33
|
-
"node-opcua-date-time": "2.
|
|
34
|
-
"node-opcua-debug": "2.
|
|
35
|
-
"node-opcua-extension-object": "2.
|
|
36
|
-
"node-opcua-factory": "2.
|
|
30
|
+
"node-opcua-crypto": "^1.12.0",
|
|
31
|
+
"node-opcua-data-model": "2.83.0",
|
|
32
|
+
"node-opcua-data-value": "2.83.0",
|
|
33
|
+
"node-opcua-date-time": "2.83.0",
|
|
34
|
+
"node-opcua-debug": "2.83.0",
|
|
35
|
+
"node-opcua-extension-object": "2.83.0",
|
|
36
|
+
"node-opcua-factory": "2.83.0",
|
|
37
37
|
"node-opcua-hostname": "2.77.0",
|
|
38
|
-
"node-opcua-nodeid": "2.
|
|
38
|
+
"node-opcua-nodeid": "2.83.0",
|
|
39
39
|
"node-opcua-nodesets": "2.77.0",
|
|
40
|
-
"node-opcua-numeric-range": "2.
|
|
41
|
-
"node-opcua-object-registry": "2.
|
|
42
|
-
"node-opcua-secure-channel": "2.
|
|
43
|
-
"node-opcua-service-browse": "2.
|
|
44
|
-
"node-opcua-service-call": "2.
|
|
45
|
-
"node-opcua-service-discovery": "2.
|
|
46
|
-
"node-opcua-service-endpoints": "2.
|
|
47
|
-
"node-opcua-service-filter": "2.
|
|
48
|
-
"node-opcua-service-history": "2.
|
|
49
|
-
"node-opcua-service-node-management": "2.
|
|
50
|
-
"node-opcua-service-query": "2.
|
|
51
|
-
"node-opcua-service-read": "2.
|
|
52
|
-
"node-opcua-service-register-node": "2.
|
|
53
|
-
"node-opcua-service-secure-channel": "2.
|
|
54
|
-
"node-opcua-service-session": "2.
|
|
55
|
-
"node-opcua-service-subscription": "2.
|
|
56
|
-
"node-opcua-service-translate-browse-path": "2.
|
|
57
|
-
"node-opcua-service-write": "2.
|
|
58
|
-
"node-opcua-status-code": "2.
|
|
59
|
-
"node-opcua-types": "2.
|
|
60
|
-
"node-opcua-utils": "2.
|
|
61
|
-
"node-opcua-variant": "2.
|
|
40
|
+
"node-opcua-numeric-range": "2.83.0",
|
|
41
|
+
"node-opcua-object-registry": "2.83.0",
|
|
42
|
+
"node-opcua-secure-channel": "2.83.0",
|
|
43
|
+
"node-opcua-service-browse": "2.83.0",
|
|
44
|
+
"node-opcua-service-call": "2.83.0",
|
|
45
|
+
"node-opcua-service-discovery": "2.83.0",
|
|
46
|
+
"node-opcua-service-endpoints": "2.83.0",
|
|
47
|
+
"node-opcua-service-filter": "2.83.0",
|
|
48
|
+
"node-opcua-service-history": "2.83.0",
|
|
49
|
+
"node-opcua-service-node-management": "2.83.0",
|
|
50
|
+
"node-opcua-service-query": "2.83.0",
|
|
51
|
+
"node-opcua-service-read": "2.83.0",
|
|
52
|
+
"node-opcua-service-register-node": "2.83.0",
|
|
53
|
+
"node-opcua-service-secure-channel": "2.83.0",
|
|
54
|
+
"node-opcua-service-session": "2.83.0",
|
|
55
|
+
"node-opcua-service-subscription": "2.83.0",
|
|
56
|
+
"node-opcua-service-translate-browse-path": "2.83.0",
|
|
57
|
+
"node-opcua-service-write": "2.83.0",
|
|
58
|
+
"node-opcua-status-code": "2.83.0",
|
|
59
|
+
"node-opcua-types": "2.83.0",
|
|
60
|
+
"node-opcua-utils": "2.83.0",
|
|
61
|
+
"node-opcua-variant": "2.83.0",
|
|
62
62
|
"thenify": "^3.3.1"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"node-opcua-data-access": "2.
|
|
66
|
-
"node-opcua-leak-detector": "2.
|
|
67
|
-
"node-opcua-pki": "^2.
|
|
65
|
+
"node-opcua-data-access": "2.83.0",
|
|
66
|
+
"node-opcua-leak-detector": "2.83.0",
|
|
67
|
+
"node-opcua-pki": "^2.18.3",
|
|
68
68
|
"node-opcua-test-helpers": "2.77.0",
|
|
69
69
|
"should": "^13.2.3",
|
|
70
|
-
"sinon": "^14.0.
|
|
70
|
+
"sinon": "^14.0.2",
|
|
71
71
|
"underscore": "^1.13.6"
|
|
72
72
|
},
|
|
73
73
|
"author": "Etienne Rossignon",
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
"internet of things"
|
|
86
86
|
],
|
|
87
87
|
"homepage": "http://node-opcua.github.io/",
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "3311f8ce9e86837fde72e923f3121072008ccdd4"
|
|
89
89
|
}
|
package/source/base_server.ts
CHANGED
|
@@ -20,7 +20,7 @@ import { coerceLocalizedText, LocalizedText } from "node-opcua-data-model";
|
|
|
20
20
|
import { installPeriodicClockAdjustment, uninstallPeriodicClockAdjustment } from "node-opcua-date-time";
|
|
21
21
|
import { checkDebugFlag, make_debugLog, make_errorLog } from "node-opcua-debug";
|
|
22
22
|
import { displayTraceFromThisProjectOnly } from "node-opcua-debug";
|
|
23
|
-
import { extractFullyQualifiedDomainName, getHostname, resolveFullyQualifiedDomainName } from "node-opcua-hostname";
|
|
23
|
+
import { extractFullyQualifiedDomainName, getFullyQualifiedDomainName, getHostname, resolveFullyQualifiedDomainName } from "node-opcua-hostname";
|
|
24
24
|
import { Message, Response, ServerSecureChannelLayer, ServerSecureChannelParent } from "node-opcua-secure-channel";
|
|
25
25
|
import { FindServersRequest, FindServersResponse } from "node-opcua-service-discovery";
|
|
26
26
|
import { ApplicationType, GetEndpointsResponse } from "node-opcua-service-endpoints";
|
|
@@ -179,14 +179,26 @@ export class OPCUABaseServer extends OPCUASecureObject {
|
|
|
179
179
|
if (fs.existsSync(this.certificateFile)) {
|
|
180
180
|
return;
|
|
181
181
|
}
|
|
182
|
+
|
|
183
|
+
// collect all hostnames
|
|
184
|
+
const hostnames = [];
|
|
185
|
+
for (const e of this.endpoints) {
|
|
186
|
+
for( const ee of e.endpointDescriptions()) {
|
|
187
|
+
/* to do */
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
182
191
|
const lockfile = path.join(this.certificateFile + ".lock");
|
|
183
192
|
await withLock({ lockfile }, async () => {
|
|
184
193
|
if (!fs.existsSync(this.certificateFile)) {
|
|
185
194
|
const applicationUri = this.serverInfo.applicationUri!;
|
|
195
|
+
const fqdn = getFullyQualifiedDomainName();
|
|
186
196
|
const hostname = getHostname();
|
|
197
|
+
const dns = [... new Set([fqdn, hostname])];
|
|
198
|
+
|
|
187
199
|
await this.serverCertificateManager.createSelfSignedCertificate({
|
|
188
200
|
applicationUri,
|
|
189
|
-
dns
|
|
201
|
+
dns,
|
|
190
202
|
// ip: await getIpAddresses(),
|
|
191
203
|
outputFile: this.certificateFile,
|
|
192
204
|
|
|
@@ -198,7 +210,7 @@ export class OPCUABaseServer extends OPCUASecureObject {
|
|
|
198
210
|
}
|
|
199
211
|
});
|
|
200
212
|
}
|
|
201
|
-
|
|
213
|
+
|
|
202
214
|
public async initializeCM(): Promise<void> {
|
|
203
215
|
await this.serverCertificateManager.initialize();
|
|
204
216
|
await this.createDefaultCertificate();
|
package/source/monitored_item.ts
CHANGED
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
isOutsideDeadbandPercent,
|
|
41
41
|
PseudoRange
|
|
42
42
|
} from "node-opcua-service-subscription";
|
|
43
|
-
import { StatusCode, StatusCodes } from "node-opcua-status-code";
|
|
43
|
+
import { CallbackT, StatusCode, StatusCodes } from "node-opcua-status-code";
|
|
44
44
|
import {
|
|
45
45
|
DataChangeNotification,
|
|
46
46
|
EventFieldList,
|
|
@@ -56,7 +56,6 @@ import { appendToTimer, removeFromTimer } from "./node_sampler";
|
|
|
56
56
|
import { validateFilter } from "./validate_filter";
|
|
57
57
|
import { checkWhereClauseOnAdressSpace } from "./filter/check_where_clause_on_address_space";
|
|
58
58
|
import { SamplingFunc } from "./sampling_func";
|
|
59
|
-
import { registerNodePromoter } from "node-opcua-address-space/source/loader/register_node_promoter";
|
|
60
59
|
|
|
61
60
|
export type QueueItem = MonitoredItemNotification | EventFieldList;
|
|
62
61
|
|
|
@@ -473,7 +472,7 @@ export class MonitoredItem extends EventEmitter {
|
|
|
473
472
|
// sampling interval.
|
|
474
473
|
const recordInitialValue =
|
|
475
474
|
old_monitoringMode === MonitoringMode.Invalid || old_monitoringMode === MonitoringMode.Disabled;
|
|
476
|
-
|
|
475
|
+
const installEventHandler = old_monitoringMode === MonitoringMode.Invalid;
|
|
477
476
|
this._start_sampling(recordInitialValue);
|
|
478
477
|
}
|
|
479
478
|
}
|
|
@@ -555,11 +554,16 @@ export class MonitoredItem extends EventEmitter {
|
|
|
555
554
|
*
|
|
556
555
|
*/
|
|
557
556
|
public recordValue(dataValue: DataValue, skipChangeTest: boolean, indexRange?: NumericRange): void {
|
|
558
|
-
|
|
557
|
+
|
|
558
|
+
if (!this.itemToMonitor) {
|
|
559
|
+
// we must have a valid itemToMonitor(have this monitoredItem been disposed already ?)
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
|
|
559
563
|
assert(dataValue !== this.oldDataValue, "recordValue expects different dataValue to be provided");
|
|
560
564
|
|
|
561
565
|
assert(
|
|
562
|
-
!dataValue.value || dataValue.value !== this.oldDataValue!.value,
|
|
566
|
+
!dataValue.value || !this.oldDataValue || dataValue.value !== this.oldDataValue!.value,
|
|
563
567
|
"recordValue expects different dataValue.value to be provided"
|
|
564
568
|
);
|
|
565
569
|
|
|
@@ -581,7 +585,6 @@ export class MonitoredItem extends EventEmitter {
|
|
|
581
585
|
}
|
|
582
586
|
}
|
|
583
587
|
|
|
584
|
-
assert(this.itemToMonitor, "must have a valid itemToMonitor(have this monitoredItem been disposed already ?");
|
|
585
588
|
// extract the range that we are interested with
|
|
586
589
|
dataValue = extractRange(dataValue, this.itemToMonitor.indexRange);
|
|
587
590
|
|
|
@@ -760,7 +763,7 @@ export class MonitoredItem extends EventEmitter {
|
|
|
760
763
|
|
|
761
764
|
this._adjust_queue_to_match_new_queue_size();
|
|
762
765
|
|
|
763
|
-
this.
|
|
766
|
+
this._adjustSampling(old_samplingInterval);
|
|
764
767
|
|
|
765
768
|
if (monitoringParameters.filter) {
|
|
766
769
|
const statusCodeFilter = validateFilter(monitoringParameters.filter, this.itemToMonitor, this.node!);
|
|
@@ -784,12 +787,11 @@ export class MonitoredItem extends EventEmitter {
|
|
|
784
787
|
}
|
|
785
788
|
|
|
786
789
|
public async resendInitialValues(): Promise<void> {
|
|
787
|
-
//
|
|
790
|
+
// the first Publish response(s) after the TransferSubscriptions call shall contain the current values of all
|
|
788
791
|
// Monitored Items in the Subscription where the Monitoring Mode is set to Reporting.
|
|
789
792
|
// the first Publish response after the TransferSubscriptions call shall contain only the value changes since
|
|
790
793
|
// the last Publish response was sent.
|
|
791
794
|
// This parameter only applies to MonitoredItems used for monitoring Attribute changes.
|
|
792
|
-
this._stop_sampling();
|
|
793
795
|
return this._start_sampling(true);
|
|
794
796
|
}
|
|
795
797
|
|
|
@@ -804,10 +806,13 @@ export class MonitoredItem extends EventEmitter {
|
|
|
804
806
|
/**
|
|
805
807
|
* @method _on_sampling_timer
|
|
806
808
|
* @private
|
|
807
|
-
* request
|
|
808
|
-
*
|
|
809
809
|
*/
|
|
810
810
|
private _on_sampling_timer() {
|
|
811
|
+
|
|
812
|
+
if (this.monitoringMode === MonitoringMode.Disabled) {
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
|
|
811
816
|
const sessionContext = this.getSessionContext();
|
|
812
817
|
if (!sessionContext) {
|
|
813
818
|
return;
|
|
@@ -971,13 +976,34 @@ export class MonitoredItem extends EventEmitter {
|
|
|
971
976
|
return this.$subscription.$session;
|
|
972
977
|
}
|
|
973
978
|
|
|
974
|
-
private _start_sampling(recordInitialValue
|
|
979
|
+
private _start_sampling(recordInitialValue: boolean): void {
|
|
975
980
|
// istanbul ignore next
|
|
976
981
|
if (!this.node) {
|
|
977
982
|
throw new Error("Internal Error");
|
|
978
983
|
}
|
|
979
984
|
setImmediate(() => this.__start_sampling(recordInitialValue));
|
|
980
985
|
}
|
|
986
|
+
|
|
987
|
+
private __acquireInitialValue(sessionContext: ISessionContext, callback: CallbackT<DataValue>): void {
|
|
988
|
+
// aquire initial value from the variable/object not itself or from the last known value if we have
|
|
989
|
+
// one already
|
|
990
|
+
assert(this.itemToMonitor.attributeId === AttributeIds.Value);
|
|
991
|
+
assert(this.node);
|
|
992
|
+
if (this.node?.nodeClass !== NodeClass.Variable) {
|
|
993
|
+
return callback(new Error("Invalid "));
|
|
994
|
+
}
|
|
995
|
+
const variable = (this.node as UAVariable);
|
|
996
|
+
if (!this.oldDataValue || this.oldDataValue.statusCode == StatusCodes.BadDataUnavailable) {
|
|
997
|
+
variable.readValueAsync(sessionContext, (err: Error | null, dataValue?: DataValue) => {
|
|
998
|
+
callback(err, dataValue);
|
|
999
|
+
});
|
|
1000
|
+
} else {
|
|
1001
|
+
const o = this.oldDataValue;
|
|
1002
|
+
this.oldDataValue = new DataValue({ statusCode: StatusCodes.BadDataUnavailable });
|
|
1003
|
+
callback(null, o);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
}
|
|
981
1007
|
private __start_sampling(recordInitialValue?: boolean): void {
|
|
982
1008
|
// istanbul ignore next
|
|
983
1009
|
if (!this.node) {
|
|
@@ -989,8 +1015,6 @@ export class MonitoredItem extends EventEmitter {
|
|
|
989
1015
|
if (!sessionContext) {
|
|
990
1016
|
return;
|
|
991
1017
|
}
|
|
992
|
-
// make sure oldDataValue is scrapped so first data recording can happen
|
|
993
|
-
this.oldDataValue = new DataValue({ statusCode: StatusCodes.BadDataUnavailable }); // unset initially
|
|
994
1018
|
|
|
995
1019
|
this._stop_sampling();
|
|
996
1020
|
|
|
@@ -999,10 +1023,11 @@ export class MonitoredItem extends EventEmitter {
|
|
|
999
1023
|
if (doDebug) {
|
|
1000
1024
|
debugLog("xxxxxx monitoring EventNotifier on", this.node.nodeId.toString(), this.node.browseName.toString());
|
|
1001
1025
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1026
|
+
if (!this._on_opcua_event_received_callback) {
|
|
1027
|
+
// we are monitoring OPCUA Event
|
|
1028
|
+
this._on_opcua_event_received_callback = this._on_opcua_event.bind(this);
|
|
1029
|
+
this.node.on("event", this._on_opcua_event_received_callback);
|
|
1030
|
+
}
|
|
1006
1031
|
return;
|
|
1007
1032
|
}
|
|
1008
1033
|
if (this.itemToMonitor.attributeId !== AttributeIds.Value) {
|
|
@@ -1010,10 +1035,11 @@ export class MonitoredItem extends EventEmitter {
|
|
|
1010
1035
|
this.samplingInterval = 0; // turned to exception-based regardless of requested sampling interval
|
|
1011
1036
|
|
|
1012
1037
|
// non value attribute only react on value change
|
|
1013
|
-
this._attribute_changed_callback
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1038
|
+
if (!this._attribute_changed_callback) {
|
|
1039
|
+
this._attribute_changed_callback = this._on_value_changed.bind(this);
|
|
1040
|
+
const event_name = makeAttributeEventName(this.itemToMonitor.attributeId);
|
|
1041
|
+
this.node.on(event_name, this._attribute_changed_callback);
|
|
1042
|
+
}
|
|
1017
1043
|
|
|
1018
1044
|
if (recordInitialValue) {
|
|
1019
1045
|
// read initial value
|
|
@@ -1026,29 +1052,32 @@ export class MonitoredItem extends EventEmitter {
|
|
|
1026
1052
|
if (this.samplingInterval === 0) {
|
|
1027
1053
|
// we have a exception-based dataItem : event based model, so we do not need a timer
|
|
1028
1054
|
// rather , we setup the "value_changed_event";
|
|
1029
|
-
this._value_changed_callback
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1055
|
+
if (!this._value_changed_callback) {
|
|
1056
|
+
assert(!this._semantic_changed_callback);
|
|
1057
|
+
this._value_changed_callback = this._on_value_changed.bind(this);
|
|
1058
|
+
this._semantic_changed_callback = this._on_semantic_changed.bind(this);
|
|
1059
|
+
this.node.on("value_changed", this._value_changed_callback);
|
|
1060
|
+
this.node.on("semantic_changed", this._semantic_changed_callback);
|
|
1061
|
+
}
|
|
1034
1062
|
|
|
1035
1063
|
// initiate first read
|
|
1036
1064
|
if (recordInitialValue) {
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
}
|
|
1042
|
-
resolve();
|
|
1043
|
-
});
|
|
1065
|
+
this.__acquireInitialValue(sessionContext, (err: Error | null, dataValue?: DataValue) => {
|
|
1066
|
+
if (!err && dataValue) {
|
|
1067
|
+
this.recordValue(dataValue, true);
|
|
1068
|
+
}
|
|
1044
1069
|
});
|
|
1045
1070
|
}
|
|
1046
1071
|
} else {
|
|
1047
|
-
this._set_timer();
|
|
1048
1072
|
if (recordInitialValue) {
|
|
1049
|
-
|
|
1050
|
-
|
|
1073
|
+
this.__acquireInitialValue(sessionContext, (err: Error | null, dataValue?: DataValue) => {
|
|
1074
|
+
if (!err && dataValue) {
|
|
1075
|
+
this.recordValue(dataValue, true);
|
|
1076
|
+
}
|
|
1077
|
+
this._set_timer();
|
|
1051
1078
|
});
|
|
1079
|
+
} else {
|
|
1080
|
+
this._set_timer();
|
|
1052
1081
|
}
|
|
1053
1082
|
}
|
|
1054
1083
|
}
|
|
@@ -1065,9 +1094,10 @@ export class MonitoredItem extends EventEmitter {
|
|
|
1065
1094
|
// that the data item is exception-based rather than being sampled at some period. An exception-based
|
|
1066
1095
|
// model means that the underlying system does not require sampling and reports data changes.
|
|
1067
1096
|
if (this.node && this.node.nodeClass === NodeClass.Variable) {
|
|
1097
|
+
const variable = (this.node as UAVariable);
|
|
1068
1098
|
this.samplingInterval = _adjust_sampling_interval(
|
|
1069
1099
|
monitoredParameters.samplingInterval,
|
|
1070
|
-
|
|
1100
|
+
variable.minimumSamplingInterval || 0
|
|
1071
1101
|
);
|
|
1072
1102
|
} else {
|
|
1073
1103
|
this.samplingInterval = _adjust_sampling_interval(monitoredParameters.samplingInterval, 0);
|
|
@@ -1197,11 +1227,11 @@ export class MonitoredItem extends EventEmitter {
|
|
|
1197
1227
|
) {
|
|
1198
1228
|
throw new Error(
|
|
1199
1229
|
"dataValue.value.value cannot be the same object twice! " +
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1230
|
+
this.node!.browseName.toString() +
|
|
1231
|
+
" " +
|
|
1232
|
+
dataValue.toString() +
|
|
1233
|
+
" " +
|
|
1234
|
+
chalk.cyan(this.oldDataValue.toString())
|
|
1205
1235
|
);
|
|
1206
1236
|
}
|
|
1207
1237
|
|
|
@@ -1248,6 +1278,13 @@ export class MonitoredItem extends EventEmitter {
|
|
|
1248
1278
|
}
|
|
1249
1279
|
|
|
1250
1280
|
private _set_timer() {
|
|
1281
|
+
|
|
1282
|
+
if(!this.itemToMonitor) {
|
|
1283
|
+
// item has already been deleted
|
|
1284
|
+
// so do not create the timer !
|
|
1285
|
+
return;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1251
1288
|
assert(this.samplingInterval >= MonitoredItem.minimumSamplingInterval);
|
|
1252
1289
|
assert(!this._samplingId);
|
|
1253
1290
|
|
|
@@ -1289,7 +1326,7 @@ export class MonitoredItem extends EventEmitter {
|
|
|
1289
1326
|
assert(this.queue.length <= this.queueSize);
|
|
1290
1327
|
}
|
|
1291
1328
|
|
|
1292
|
-
private
|
|
1329
|
+
private _adjustSampling(old_samplingInterval: number) {
|
|
1293
1330
|
if (old_samplingInterval !== this.samplingInterval) {
|
|
1294
1331
|
this._start_sampling(false);
|
|
1295
1332
|
}
|
package/source/node_sampler.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { assert } from "node-opcua-assert";
|
|
5
5
|
import { checkDebugFlag, make_debugLog } from "node-opcua-debug";
|
|
6
|
+
import { MonitoringMode } from "node-opcua-types";
|
|
6
7
|
import { hrtime } from "node-opcua-utils";
|
|
7
8
|
|
|
8
9
|
const debugLog = make_debugLog(__filename);
|
|
@@ -18,6 +19,11 @@ interface MonitoredItemPriv {
|
|
|
18
19
|
}
|
|
19
20
|
function sampleMonitoredItem(monitoredItem: MonitoredItem) {
|
|
20
21
|
const _monitoredItem = monitoredItem as unknown as MonitoredItemPriv;
|
|
22
|
+
|
|
23
|
+
if (monitoredItem.monitoringMode === MonitoringMode.Disabled) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
21
27
|
setImmediate(() => {
|
|
22
28
|
_monitoredItem._on_sampling_timer();
|
|
23
29
|
});
|
package/source/opcua_server.ts
CHANGED
|
@@ -1141,7 +1141,7 @@ export class OPCUAServer extends OPCUABaseServer {
|
|
|
1141
1141
|
});
|
|
1142
1142
|
this.objectFactory = new Factory(this.engine);
|
|
1143
1143
|
|
|
1144
|
-
const endpointDefinitions = options.alternateEndpoints || [];
|
|
1144
|
+
const endpointDefinitions: OPCUAServerEndpointOptions[] = options.alternateEndpoints || [];
|
|
1145
1145
|
const hostname = getFullyQualifiedDomainName();
|
|
1146
1146
|
|
|
1147
1147
|
endpointDefinitions.push({
|
|
@@ -1154,7 +1154,6 @@ export class OPCUAServer extends OPCUABaseServer {
|
|
|
1154
1154
|
securityModes: options.securityModes,
|
|
1155
1155
|
securityPolicies: options.securityPolicies
|
|
1156
1156
|
});
|
|
1157
|
-
|
|
1158
1157
|
// todo should self.serverInfo.productUri match self.engine.buildInfo.productUri ?
|
|
1159
1158
|
for (const endpointOptions of endpointDefinitions) {
|
|
1160
1159
|
const endPoint = this.createEndpointDescriptions(options!, endpointOptions);
|
|
@@ -1753,7 +1752,7 @@ export class OPCUAServer extends OPCUABaseServer {
|
|
|
1753
1752
|
function rejectConnection(server: OPCUAServer, statusCode: StatusCode): void {
|
|
1754
1753
|
server.engine.incrementSecurityRejectedSessionCount();
|
|
1755
1754
|
|
|
1756
|
-
const response1 = new
|
|
1755
|
+
const response1 = new ServiceFault({
|
|
1757
1756
|
responseHeader: { serviceResult: statusCode }
|
|
1758
1757
|
});
|
|
1759
1758
|
channel.send_response("MSG", response1, message);
|
|
@@ -3507,7 +3506,7 @@ export class OPCUAServer extends OPCUABaseServer {
|
|
|
3507
3506
|
return g_sendError(channel, message, HistoryUpdateResponse, StatusCodes.BadServiceUnsupported);
|
|
3508
3507
|
}
|
|
3509
3508
|
|
|
3510
|
-
private createEndpoint(port1: number, serverOptions:
|
|
3509
|
+
private createEndpoint(port1: number, serverOptions: {defaultSecureTokenLifetime?: number, timeout? : number}): OPCUAServerEndPoint {
|
|
3511
3510
|
// add the tcp/ip endpoint with no security
|
|
3512
3511
|
const endPoint = new OPCUAServerEndPoint({
|
|
3513
3512
|
port: port1,
|