node-opcua-address-space 2.102.0 → 2.103.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/source/namespace_data_access.d.ts +20 -1
- package/dist/source/pseudo_session.js +11 -2
- package/dist/source/pseudo_session.js.map +1 -1
- package/dist/source/session_context.js +3 -0
- package/dist/source/session_context.js.map +1 -1
- package/dist/src/data_access/adjust_datavalue_status_code.d.ts +4 -0
- package/dist/src/data_access/adjust_datavalue_status_code.js +30 -0
- package/dist/src/data_access/adjust_datavalue_status_code.js.map +1 -0
- package/dist/src/index_current.d.ts +1 -1
- package/dist/src/index_current.js +1 -1
- package/dist/src/index_current.js.map +1 -1
- package/dist/src/namespace_impl.js +3 -1
- package/dist/src/namespace_impl.js.map +1 -1
- package/dist/src/ua_variable_impl.d.ts +1 -0
- package/dist/src/ua_variable_impl.js +25 -6
- package/dist/src/ua_variable_impl.js.map +1 -1
- package/dist/tsconfig_common.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/source/namespace_data_access.ts +27 -2
- package/source/pseudo_session.ts +12 -4
- package/source/session_context.ts +1 -0
- package/src/data_access/adjust_datavalue_status_code.ts +36 -0
- package/src/index_current.ts +1 -1
- package/src/namespace_impl.ts +36 -30
- package/src/ua_variable_impl.ts +26 -6
- package/src/data_access/check_variant_compatibility_ua_analog_item.ts +0 -38
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-opcua-address-space",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.103.0",
|
|
4
4
|
"description": "pure nodejs OPCUA SDK - module address-space",
|
|
5
5
|
"main": "./dist/src/index_current.js",
|
|
6
6
|
"types": "./dist/source/index.d.ts",
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
"chalk": "4.1.2",
|
|
23
23
|
"dequeue": "^1.0.5",
|
|
24
24
|
"lodash": "4.17.21",
|
|
25
|
-
"node-opcua-address-space-base": "2.
|
|
25
|
+
"node-opcua-address-space-base": "2.103.0",
|
|
26
26
|
"node-opcua-assert": "2.98.1",
|
|
27
27
|
"node-opcua-basic-types": "2.99.0",
|
|
28
28
|
"node-opcua-binary-stream": "2.98.1",
|
|
29
|
-
"node-opcua-client-dynamic-extension-object": "2.
|
|
29
|
+
"node-opcua-client-dynamic-extension-object": "2.103.0",
|
|
30
30
|
"node-opcua-constants": "2.98.1",
|
|
31
31
|
"node-opcua-crypto": "^2.1.2",
|
|
32
|
-
"node-opcua-data-access": "2.
|
|
32
|
+
"node-opcua-data-access": "2.103.0",
|
|
33
33
|
"node-opcua-data-model": "2.102.0",
|
|
34
34
|
"node-opcua-data-value": "2.102.0",
|
|
35
35
|
"node-opcua-date-time": "2.99.0",
|
|
@@ -38,20 +38,20 @@
|
|
|
38
38
|
"node-opcua-extension-object": "2.99.0",
|
|
39
39
|
"node-opcua-factory": "2.99.0",
|
|
40
40
|
"node-opcua-nodeid": "2.99.0",
|
|
41
|
-
"node-opcua-nodeset-ua": "2.
|
|
41
|
+
"node-opcua-nodeset-ua": "2.103.0",
|
|
42
42
|
"node-opcua-numeric-range": "2.102.0",
|
|
43
43
|
"node-opcua-object-registry": "2.99.0",
|
|
44
|
-
"node-opcua-pseudo-session": "2.
|
|
45
|
-
"node-opcua-service-browse": "2.
|
|
46
|
-
"node-opcua-service-call": "2.
|
|
47
|
-
"node-opcua-service-history": "2.
|
|
48
|
-
"node-opcua-service-translate-browse-path": "2.
|
|
49
|
-
"node-opcua-service-write": "2.
|
|
44
|
+
"node-opcua-pseudo-session": "2.103.0",
|
|
45
|
+
"node-opcua-service-browse": "2.103.0",
|
|
46
|
+
"node-opcua-service-call": "2.103.0",
|
|
47
|
+
"node-opcua-service-history": "2.103.0",
|
|
48
|
+
"node-opcua-service-translate-browse-path": "2.103.0",
|
|
49
|
+
"node-opcua-service-write": "2.103.0",
|
|
50
50
|
"node-opcua-status-code": "2.98.1",
|
|
51
|
-
"node-opcua-types": "2.
|
|
51
|
+
"node-opcua-types": "2.103.0",
|
|
52
52
|
"node-opcua-utils": "2.98.1",
|
|
53
53
|
"node-opcua-variant": "2.102.0",
|
|
54
|
-
"node-opcua-xml2json": "2.
|
|
54
|
+
"node-opcua-xml2json": "2.103.0",
|
|
55
55
|
"semver": "^7.3.8",
|
|
56
56
|
"set-prototype-of": "^1.0.0",
|
|
57
57
|
"thenify": "^3.3.1",
|
|
@@ -61,10 +61,10 @@
|
|
|
61
61
|
"mocha": "^10.2.0",
|
|
62
62
|
"node-opcua-benchmarker": "2.98.1",
|
|
63
63
|
"node-opcua-leak-detector": "2.99.0",
|
|
64
|
-
"node-opcua-nodesets": "2.
|
|
64
|
+
"node-opcua-nodesets": "2.103.0",
|
|
65
65
|
"node-opcua-packet-analyzer": "2.102.0",
|
|
66
|
-
"node-opcua-service-filter": "2.
|
|
67
|
-
"node-opcua-test-fixtures": "2.
|
|
66
|
+
"node-opcua-service-filter": "2.103.0",
|
|
67
|
+
"node-opcua-test-fixtures": "2.103.0",
|
|
68
68
|
"should": "^13.2.3",
|
|
69
69
|
"sinon": "^15.0.3",
|
|
70
70
|
"source-map-support": "^0.5.21"
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"internet of things"
|
|
85
85
|
],
|
|
86
86
|
"homepage": "http://node-opcua.github.io/",
|
|
87
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "e206cac2daf39bd07e5ac6cbd744f966bb54759e",
|
|
88
88
|
"files": [
|
|
89
89
|
"dist",
|
|
90
90
|
"distHelpers",
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AddVariableOptionsWithoutValue,
|
|
3
|
+
AddYArrayItemOptions,
|
|
4
|
+
BindVariableOptions,
|
|
5
|
+
UADataType
|
|
6
|
+
} from "node-opcua-address-space-base";
|
|
2
7
|
import { NodeIdLike } from "node-opcua-nodeid";
|
|
3
8
|
import { UAAnalogItem, UADataItem } from "node-opcua-nodeset-ua";
|
|
4
9
|
import { EUInformation, EUInformationOptions } from "node-opcua-types";
|
|
@@ -40,11 +45,31 @@ export interface AddAnalogDataItemOptions extends AddDataItemOptions {
|
|
|
40
45
|
engineeringUnits?: EUInformationOptions | EUInformation;
|
|
41
46
|
minimumSamplingInterval?: number;
|
|
42
47
|
dataType?: string | NodeIdLike | UADataType;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* the acceptValueOutOfRange property indicates whether the write operation will accept or reject a value which
|
|
51
|
+
* is out of range of the instrumentRange.
|
|
52
|
+
*
|
|
53
|
+
* **if true**: during a writeOperation by a client if the dataValue that is outside of the instrumentRange
|
|
54
|
+
* it will be recorded database and the statusCode will be set to BadOutOfRange, and
|
|
55
|
+
* the write operation will return Good. If the variable supports historizing, the value will be recorded in the history database.
|
|
56
|
+
* as well.
|
|
57
|
+
*
|
|
58
|
+
* **if false**: during a writeOperation by a client, if the dataValue that is outside of the instrumentRange
|
|
59
|
+
* it will be denied and the write operation will return BadOutOfRange.
|
|
60
|
+
*
|
|
61
|
+
* @default undefined (false)
|
|
62
|
+
*
|
|
63
|
+
*/
|
|
64
|
+
acceptValueOutOfRange?: boolean;
|
|
43
65
|
}
|
|
44
66
|
|
|
67
|
+
export interface UAAnalogItemEx<T, DT extends DataType> extends UAAnalogItem<T, DT> {
|
|
68
|
+
acceptValueOutOfRange?: boolean;
|
|
69
|
+
}
|
|
45
70
|
export interface INamespaceDataAccess {
|
|
46
71
|
addDataItem<T, DT extends DataType>(options: AddDataItemOptions): UADataItem<T, DT>;
|
|
47
|
-
addAnalogDataItem<T, DT extends DataType>(options: AddAnalogDataItemOptions):
|
|
72
|
+
addAnalogDataItem<T, DT extends DataType>(options: AddAnalogDataItemOptions): UAAnalogItemEx<T, DT>;
|
|
48
73
|
|
|
49
74
|
addYArrayItem<DT extends DataType.Double | DataType.Float>(options: AddYArrayItemOptions): UAYArrayItemEx<DT>;
|
|
50
75
|
|
package/source/pseudo_session.ts
CHANGED
|
@@ -352,11 +352,19 @@ export class PseudoSession implements IBasicSession {
|
|
|
352
352
|
if (!obj) {
|
|
353
353
|
return StatusCodes.BadNodeIdUnknown;
|
|
354
354
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
355
|
+
try {
|
|
356
|
+
return promisify(obj.writeAttribute).call(obj, context, nodeToWrite);
|
|
357
|
+
} catch (err) {
|
|
358
|
+
return StatusCodes.BadInternalError;
|
|
359
|
+
}
|
|
359
360
|
});
|
|
361
|
+
Promise.all(statusCodesPromises)
|
|
362
|
+
.then((statusCodes) => {
|
|
363
|
+
callback!(null, isArray ? statusCodes : statusCodes[0]);
|
|
364
|
+
})
|
|
365
|
+
.catch((err) => {
|
|
366
|
+
callback!(err);
|
|
367
|
+
});
|
|
360
368
|
});
|
|
361
369
|
}
|
|
362
370
|
}
|
|
@@ -305,6 +305,7 @@ export class SessionContext implements ISessionContext {
|
|
|
305
305
|
return true;
|
|
306
306
|
}
|
|
307
307
|
}
|
|
308
|
+
if (!this.session ) { return false; }
|
|
308
309
|
const securityMode = this.session?.channel?.securityMode;
|
|
309
310
|
if (accessRestrictions & AccessRestrictionsFlag.SigningRequired) {
|
|
310
311
|
if (securityMode !== MessageSecurityMode.Sign && securityMode !== MessageSecurityMode.SignAndEncrypt) {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module node-opcua-address-space.DataAccess
|
|
3
|
+
*/
|
|
4
|
+
import { StatusCodes } from "node-opcua-status-code";
|
|
5
|
+
import { StatusCode } from "node-opcua-status-code";
|
|
6
|
+
import { Range } from "node-opcua-types";
|
|
7
|
+
import { UAVariable } from "node-opcua-address-space-base";
|
|
8
|
+
import { NodeClass } from "node-opcua-data-model";
|
|
9
|
+
import { DataValue } from "node-opcua-data-value";
|
|
10
|
+
import { Variant } from "node-opcua-variant";
|
|
11
|
+
import { UAVariableImpl } from "../ua_variable_impl";
|
|
12
|
+
|
|
13
|
+
function validate_value_range(range: Range, variant: Variant) {
|
|
14
|
+
if (variant.value < range.low || variant.value > range.high) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function adjustDataValueStatusCode(
|
|
21
|
+
variable: UAVariableImpl,
|
|
22
|
+
dataValue: DataValue,
|
|
23
|
+
acceptValueOutOfRange: boolean
|
|
24
|
+
): StatusCode {
|
|
25
|
+
const instrumentRange = variable.getChildByName("InstrumentRange") as UAVariable | null;
|
|
26
|
+
if (instrumentRange && instrumentRange.nodeClass === NodeClass.Variable) {
|
|
27
|
+
if (!validate_value_range(instrumentRange.readValue().value.value as Range, dataValue.value)) {
|
|
28
|
+
if (!acceptValueOutOfRange) {
|
|
29
|
+
return StatusCodes.BadOutOfRange;
|
|
30
|
+
} else {
|
|
31
|
+
dataValue.statusCode = StatusCodes.BadOutOfRange;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return StatusCodes.Good;
|
|
36
|
+
}
|
package/src/index_current.ts
CHANGED
|
@@ -43,7 +43,7 @@ export { adjustNamespaceArray } from "./nodeset_tools/adjust_namespace_array";
|
|
|
43
43
|
export { makeAttributeEventName } from "./base_node_impl";
|
|
44
44
|
export { resolveReferenceNode, resolveReferenceType } from "./reference_impl";
|
|
45
45
|
|
|
46
|
-
export * from "./data_access/
|
|
46
|
+
export * from "./data_access/adjust_datavalue_status_code";
|
|
47
47
|
export * from "./data_access/add_dataItem_stuff";
|
|
48
48
|
export * from "./data_access/ua_multistate_discrete_impl";
|
|
49
49
|
export * from "./data_access/ua_multistate_value_discrete_impl";
|
package/src/namespace_impl.ts
CHANGED
|
@@ -76,7 +76,7 @@ import {
|
|
|
76
76
|
UATwoStateDiscreteEx,
|
|
77
77
|
UAYArrayItemEx
|
|
78
78
|
} from "../source";
|
|
79
|
-
import { AddAnalogDataItemOptions, AddDataItemOptions } from "../source/namespace_data_access";
|
|
79
|
+
import { AddAnalogDataItemOptions, AddDataItemOptions, UAAnalogItemEx } from "../source/namespace_data_access";
|
|
80
80
|
import { UATwoStateVariableEx } from "../source/ua_two_state_variable_ex";
|
|
81
81
|
import { UAMultiStateValueDiscreteEx } from "../source/interfaces/data_access/ua_multistate_value_discrete_ex";
|
|
82
82
|
import { UAAlarmConditionEx } from "../source/interfaces/alarms_and_conditions/ua_alarm_condition_ex";
|
|
@@ -125,7 +125,6 @@ import { UAViewImpl } from "./ua_view_impl";
|
|
|
125
125
|
import { UAStateMachineImpl, UATransitionImpl } from "./state_machine/finite_state_machine";
|
|
126
126
|
import { _addMultiStateValueDiscrete } from "./data_access/ua_multistate_value_discrete_impl";
|
|
127
127
|
|
|
128
|
-
|
|
129
128
|
function _makeHashKey(nodeId: NodeId): string | number {
|
|
130
129
|
switch (nodeId.identifierType) {
|
|
131
130
|
case NodeIdType.STRING:
|
|
@@ -931,6 +930,7 @@ export class NamespaceImpl implements NamespacePrivate {
|
|
|
931
930
|
|
|
932
931
|
instrumentRange.on("value_changed", handler);
|
|
933
932
|
}
|
|
933
|
+
(variable as any).acceptValueOutOfRange = options.acceptValueOutOfRange;
|
|
934
934
|
|
|
935
935
|
if (Object.prototype.hasOwnProperty.call(options, "engineeringUnits")) {
|
|
936
936
|
const engineeringUnits = new EUInformation(options.engineeringUnits);
|
|
@@ -1445,7 +1445,7 @@ export class NamespaceImpl implements NamespacePrivate {
|
|
|
1445
1445
|
const _component = component as UAStateMachineImpl;
|
|
1446
1446
|
|
|
1447
1447
|
assert(_component.nodeClass === NodeClass.Object || _component.nodeClass === NodeClass.ObjectType);
|
|
1448
|
-
|
|
1448
|
+
|
|
1449
1449
|
const initialStateType = addressSpace.findObjectType("InitialStateType")!;
|
|
1450
1450
|
const stateType = addressSpace.findObjectType("StateType")!;
|
|
1451
1451
|
|
|
@@ -1662,24 +1662,24 @@ export class NamespaceImpl implements NamespacePrivate {
|
|
|
1662
1662
|
|
|
1663
1663
|
// istanbul ignore next
|
|
1664
1664
|
if (this._nodeid_index.has(hashKey)) {
|
|
1665
|
-
|
|
1666
1665
|
const exstingNode = this.findNode(node.nodeId)!;
|
|
1667
1666
|
throw new Error(
|
|
1668
1667
|
"node " +
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1668
|
+
node.browseName.toString() +
|
|
1669
|
+
" nodeId = " +
|
|
1670
|
+
node.nodeId.displayText() +
|
|
1671
|
+
" already registered " +
|
|
1672
|
+
node.nodeId.toString() +
|
|
1673
|
+
"\n" +
|
|
1674
|
+
" in namespace " +
|
|
1675
|
+
this.namespaceUri +
|
|
1676
|
+
" index = " +
|
|
1677
|
+
this.index +
|
|
1678
|
+
"\n" +
|
|
1679
|
+
"existing node = " +
|
|
1680
|
+
exstingNode.toString() +
|
|
1681
|
+
"this parent : " +
|
|
1682
|
+
node.parentNodeId?.toString()
|
|
1683
1683
|
);
|
|
1684
1684
|
}
|
|
1685
1685
|
|
|
@@ -1742,15 +1742,15 @@ export class NamespaceImpl implements NamespacePrivate {
|
|
|
1742
1742
|
errorLog(
|
|
1743
1743
|
chalk.red.bold(
|
|
1744
1744
|
"Error: namespace index used at the front of the browseName " +
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1745
|
+
indexVerif +
|
|
1746
|
+
" do not match the index of the current namespace (" +
|
|
1747
|
+
this.index +
|
|
1748
|
+
")"
|
|
1749
1749
|
)
|
|
1750
1750
|
);
|
|
1751
1751
|
errorLog(
|
|
1752
1752
|
" Please fix your code so that the created node is inserted in the correct namespace," +
|
|
1753
|
-
|
|
1753
|
+
" please refer to the NodeOPCUA documentation"
|
|
1754
1754
|
);
|
|
1755
1755
|
}
|
|
1756
1756
|
}
|
|
@@ -1990,13 +1990,16 @@ export class NamespaceImpl implements NamespacePrivate {
|
|
|
1990
1990
|
|
|
1991
1991
|
// -----------------------------------------------------
|
|
1992
1992
|
const hasGetter = (options: AddVariableOptions2) => {
|
|
1993
|
-
return typeof options.value?.get === "function" || typeof options.value?.timestamped_get === "function"
|
|
1994
|
-
}
|
|
1993
|
+
return typeof options.value?.get === "function" || typeof options.value?.timestamped_get === "function";
|
|
1994
|
+
};
|
|
1995
1995
|
|
|
1996
1996
|
// istanbul ignore next
|
|
1997
1997
|
if (options.minimumSamplingInterval === undefined && hasGetter(options)) {
|
|
1998
1998
|
// a getter has been specified and no options.minimumSamplingInterval has been specified
|
|
1999
|
-
warningLog(
|
|
1999
|
+
warningLog(
|
|
2000
|
+
"[NODE-OPCUA-W30",
|
|
2001
|
+
"namespace#addVariable a getter has been specified and minimumSamplingInterval is missing.\nMinimumSamplingInterval has been adjusted to 1000 ms"
|
|
2002
|
+
);
|
|
2000
2003
|
options.minimumSamplingInterval = 1000;
|
|
2001
2004
|
}
|
|
2002
2005
|
|
|
@@ -2004,7 +2007,10 @@ export class NamespaceImpl implements NamespacePrivate {
|
|
|
2004
2007
|
|
|
2005
2008
|
// istanbul ignore next
|
|
2006
2009
|
if (options.minimumSamplingInterval === 0 && hasGetter(options)) {
|
|
2007
|
-
warningLog(
|
|
2010
|
+
warningLog(
|
|
2011
|
+
"[NODE-OPCUA-W31",
|
|
2012
|
+
"namespace#addVariable a getter has been specified and minimumSamplingInterval is 0.\nThis may conduct to an unpredicable behavior.\nPlease specify a non zero minimum sampling interval"
|
|
2013
|
+
);
|
|
2008
2014
|
}
|
|
2009
2015
|
|
|
2010
2016
|
let references = options.references || ([] as AddReferenceOpts[]);
|
|
@@ -2209,15 +2215,15 @@ export function isNonEmptyQualifiedName(browseName?: null | string | QualifiedNa
|
|
|
2209
2215
|
return browseName.name!.length > 0;
|
|
2210
2216
|
}
|
|
2211
2217
|
|
|
2212
|
-
function _create_node_version_if_needed(node: BaseNode, options: {nodeVersion: boolean}) {
|
|
2218
|
+
function _create_node_version_if_needed(node: BaseNode, options: { nodeVersion: boolean }) {
|
|
2213
2219
|
assert(options);
|
|
2214
2220
|
if (options.nodeVersion) {
|
|
2215
2221
|
assert(node.nodeClass === NodeClass.Variable || node.nodeClass === NodeClass.Object);
|
|
2216
2222
|
// istanbul ignore next
|
|
2217
|
-
if (node.getChildByName("NodeVersion"))
|
|
2223
|
+
if (node.getChildByName("NodeVersion")) {
|
|
2218
2224
|
return; // already exists
|
|
2219
2225
|
}
|
|
2220
|
-
const namespace
|
|
2226
|
+
const namespace = node.addressSpace.getOwnNamespace();
|
|
2221
2227
|
const nodeVersion = namespace.addVariable({
|
|
2222
2228
|
browseName: "NodeVersion",
|
|
2223
2229
|
dataType: "String",
|
package/src/ua_variable_impl.ts
CHANGED
|
@@ -96,6 +96,7 @@ import {
|
|
|
96
96
|
_installExtensionObjectBindingOnProperties,
|
|
97
97
|
_touchValue
|
|
98
98
|
} from "./ua_variable_impl_ext_obj";
|
|
99
|
+
import { adjustDataValueStatusCode } from "./data_access/adjust_datavalue_status_code";
|
|
99
100
|
|
|
100
101
|
const debugLog = make_debugLog(__filename);
|
|
101
102
|
const warningLog = make_warningLog(__filename);
|
|
@@ -849,7 +850,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
849
850
|
// ----------------------------------
|
|
850
851
|
if (this.$extensionObject || this.$$extensionObjectArray) {
|
|
851
852
|
// we have an extension object already bound to this node
|
|
852
|
-
// the client is asking us to replace the object
|
|
853
|
+
// the client is asking us to replace the object entirely by a new one
|
|
853
854
|
// const ext = dataValue.value.value;
|
|
854
855
|
this._internal_set_dataValue(dataValue);
|
|
855
856
|
return;
|
|
@@ -867,6 +868,11 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
867
868
|
}
|
|
868
869
|
}
|
|
869
870
|
|
|
871
|
+
private adjustDataValueStatusCode(dataValue: DataValue): StatusCode {
|
|
872
|
+
const statusCode = adjustDataValueStatusCode(this, dataValue, (this as any).acceptValueOutOfRange || false);
|
|
873
|
+
return statusCode;
|
|
874
|
+
}
|
|
875
|
+
|
|
870
876
|
public writeValue(
|
|
871
877
|
context: ISessionContext,
|
|
872
878
|
dataValue: DataValue,
|
|
@@ -939,6 +945,12 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
939
945
|
return callback!(null, statusCode);
|
|
940
946
|
}
|
|
941
947
|
|
|
948
|
+
// adjust dataValue.statusCode based on InstrumentRange and EngineeringUnits
|
|
949
|
+
const statusCode2 = this.adjustDataValueStatusCode(dataValue);
|
|
950
|
+
if (statusCode2.isNotGood()) {
|
|
951
|
+
return callback!(null, statusCode2);
|
|
952
|
+
}
|
|
953
|
+
|
|
942
954
|
const write_func = this._timestamped_set_func || default_func;
|
|
943
955
|
|
|
944
956
|
if (!write_func) {
|
|
@@ -1281,7 +1293,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1281
1293
|
|
|
1282
1294
|
const readImmediate = (innerCallback: (err: Error | null, dataValue: DataValue) => void) => {
|
|
1283
1295
|
assert(this.$dataValue instanceof DataValue);
|
|
1284
|
-
const dataValue = this.readValue();
|
|
1296
|
+
const dataValue = this.readValue(context);
|
|
1285
1297
|
innerCallback(null, dataValue);
|
|
1286
1298
|
};
|
|
1287
1299
|
|
|
@@ -2046,10 +2058,14 @@ function _default_writable_timestamped_set_func(
|
|
|
2046
2058
|
function turn_sync_to_async<T, D, R>(f: (this: T, data: D) => R, numberOfArgs: number) {
|
|
2047
2059
|
if (f.length <= numberOfArgs) {
|
|
2048
2060
|
return function (this: T, data: D, callback: (err: Error | null, r?: R) => void) {
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2061
|
+
try {
|
|
2062
|
+
const r = f.call(this, data);
|
|
2063
|
+
setImmediate(() => {
|
|
2064
|
+
return callback(null, r);
|
|
2065
|
+
});
|
|
2066
|
+
} catch (err) {
|
|
2067
|
+
return callback(err as Error);
|
|
2068
|
+
}
|
|
2053
2069
|
};
|
|
2054
2070
|
} else {
|
|
2055
2071
|
assert(f.length === numberOfArgs + 1);
|
|
@@ -2209,6 +2225,10 @@ function _Variable_bind_with_simple_set(this: UAVariableImpl, options: any) {
|
|
|
2209
2225
|
errorLog(chalk.yellow("StatusCode.Good is assumed"));
|
|
2210
2226
|
return callback(err, StatusCodes.Good, timestamped_value);
|
|
2211
2227
|
}
|
|
2228
|
+
if (statusCode && statusCode.isNotGood()) {
|
|
2229
|
+
// record the value but still record the statusCode !
|
|
2230
|
+
timestamped_value.statusCode = statusCode;
|
|
2231
|
+
}
|
|
2212
2232
|
callback(err, statusCode, timestamped_value);
|
|
2213
2233
|
});
|
|
2214
2234
|
};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module node-opcua-address-space.DataAccess
|
|
3
|
-
*/
|
|
4
|
-
import { assert } from "node-opcua-assert";
|
|
5
|
-
import { UAAnalogItem } from "node-opcua-nodeset-ua";
|
|
6
|
-
import { StatusCodes } from "node-opcua-status-code";
|
|
7
|
-
import { StatusCode } from "node-opcua-status-code";
|
|
8
|
-
import { Range } from "node-opcua-types";
|
|
9
|
-
import { DataType, Variant } from "node-opcua-variant";
|
|
10
|
-
import { UAVariableImpl } from "../ua_variable_impl";
|
|
11
|
-
|
|
12
|
-
function validate_value_range(range: Range, variant: Variant) {
|
|
13
|
-
if (variant.value < range.low || variant.value > range.high) {
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
return true;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function checkVariantCompatibilityUAAnalogItem(this: UAVariableImpl, value: Variant): StatusCode {
|
|
20
|
-
assert(value instanceof Variant);
|
|
21
|
-
// test dataType
|
|
22
|
-
if (!this._validate_DataType(value.dataType)) {
|
|
23
|
-
return StatusCodes.BadTypeMismatch;
|
|
24
|
-
}
|
|
25
|
-
const analogItem = this as unknown as UAAnalogItem<any, any>;
|
|
26
|
-
// AnalogDataItem
|
|
27
|
-
if (analogItem.instrumentRange) {
|
|
28
|
-
if (!validate_value_range(analogItem.instrumentRange.readValue().value.value as Range, value)) {
|
|
29
|
-
return StatusCodes.BadOutOfRange;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return StatusCodes.Good;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* extend default checkVariantCompatibility on base class with this one
|
|
37
|
-
*/
|
|
38
|
-
UAVariableImpl.prototype.checkVariantCompatibility = checkVariantCompatibilityUAAnalogItem;
|