node-opcua-address-space 2.118.0 → 2.119.2

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.
Files changed (66) hide show
  1. package/dist/source/helpers/coerce_enum_value.js +1 -1
  2. package/dist/source/helpers/coerce_enum_value.js.map +1 -1
  3. package/dist/source/index.d.ts +1 -0
  4. package/dist/source/index.js +5 -2
  5. package/dist/source/index.js.map +1 -1
  6. package/dist/source/interfaces/alarms_and_conditions/condition_info_i.d.ts +2 -0
  7. package/dist/source/interfaces/alarms_and_conditions/condition_snapshot.d.ts +14 -6
  8. package/dist/source/interfaces/alarms_and_conditions/ua_condition_ex.d.ts +3 -2
  9. package/dist/source/interfaces/data_access/ua_multistate_discrete_ex.d.ts +26 -3
  10. package/dist/source/interfaces/data_access/ua_multistate_value_discrete_ex.d.ts +2 -1
  11. package/dist/source/interfaces/data_access/ua_two_state_discrete_ex.d.ts +2 -1
  12. package/dist/source/interfaces/i_condition_variable_type_setter_options.d.ts +3 -0
  13. package/dist/source/interfaces/i_condition_variable_type_setter_options.js +3 -0
  14. package/dist/source/interfaces/i_condition_variable_type_setter_options.js.map +1 -0
  15. package/dist/source/interfaces/i_set_state_options.d.ts +4 -0
  16. package/dist/source/interfaces/i_set_state_options.js +3 -0
  17. package/dist/source/interfaces/i_set_state_options.js.map +1 -0
  18. package/dist/source/ua_two_state_variable_ex.d.ts +2 -1
  19. package/dist/src/alarms_and_conditions/condition.d.ts +2 -1
  20. package/dist/src/alarms_and_conditions/condition.js +2 -2
  21. package/dist/src/alarms_and_conditions/condition.js.map +1 -1
  22. package/dist/src/alarms_and_conditions/condition_snapshot_impl.d.ts +20 -11
  23. package/dist/src/alarms_and_conditions/condition_snapshot_impl.js +72 -33
  24. package/dist/src/alarms_and_conditions/condition_snapshot_impl.js.map +1 -1
  25. package/dist/src/alarms_and_conditions/ua_condition_impl.d.ts +3 -2
  26. package/dist/src/alarms_and_conditions/ua_condition_impl.js +13 -26
  27. package/dist/src/alarms_and_conditions/ua_condition_impl.js.map +1 -1
  28. package/dist/src/data_access/ua_multistate_discrete_impl.d.ts +3 -2
  29. package/dist/src/data_access/ua_multistate_discrete_impl.js +2 -2
  30. package/dist/src/data_access/ua_multistate_discrete_impl.js.map +1 -1
  31. package/dist/src/data_access/ua_multistate_value_discrete_impl.d.ts +8 -5
  32. package/dist/src/data_access/ua_multistate_value_discrete_impl.js +91 -50
  33. package/dist/src/data_access/ua_multistate_value_discrete_impl.js.map +1 -1
  34. package/dist/src/data_access/ua_two_state_discrete_impl.d.ts +2 -1
  35. package/dist/src/data_access/ua_two_state_discrete_impl.js +3 -3
  36. package/dist/src/data_access/ua_two_state_discrete_impl.js.map +1 -1
  37. package/dist/src/get_basic_datatype.d.ts +4 -1
  38. package/dist/src/get_basic_datatype.js +12 -7
  39. package/dist/src/get_basic_datatype.js.map +1 -1
  40. package/dist/src/nodeset_tools/construct_namespace_dependency.js +1 -1
  41. package/dist/src/nodeset_tools/construct_namespace_dependency.js.map +1 -1
  42. package/dist/src/state_machine/ua_two_state_variable.d.ts +2 -1
  43. package/dist/src/state_machine/ua_two_state_variable.js +10 -8
  44. package/dist/src/state_machine/ua_two_state_variable.js.map +1 -1
  45. package/dist/tsconfig_common.tsbuildinfo +1 -1
  46. package/package.json +27 -27
  47. package/source/helpers/coerce_enum_value.ts +2 -2
  48. package/source/index.ts +2 -0
  49. package/source/interfaces/alarms_and_conditions/condition_info_i.ts +4 -0
  50. package/source/interfaces/alarms_and_conditions/condition_snapshot.ts +13 -8
  51. package/source/interfaces/alarms_and_conditions/ua_condition_ex.ts +4 -2
  52. package/source/interfaces/data_access/ua_multistate_discrete_ex.ts +39 -3
  53. package/source/interfaces/data_access/ua_multistate_value_discrete_ex.ts +2 -1
  54. package/source/interfaces/data_access/ua_two_state_discrete_ex.ts +2 -1
  55. package/source/interfaces/i_condition_variable_type_setter_options.ts +5 -0
  56. package/source/interfaces/i_set_state_options.ts +4 -0
  57. package/source/ua_two_state_variable_ex.ts +2 -1
  58. package/src/alarms_and_conditions/condition.ts +4 -2
  59. package/src/alarms_and_conditions/condition_snapshot_impl.ts +75 -38
  60. package/src/alarms_and_conditions/ua_condition_impl.ts +14 -27
  61. package/src/data_access/ua_multistate_discrete_impl.ts +5 -3
  62. package/src/data_access/ua_multistate_value_discrete_impl.ts +109 -55
  63. package/src/data_access/ua_two_state_discrete_impl.ts +5 -3
  64. package/src/get_basic_datatype.ts +16 -7
  65. package/src/nodeset_tools/construct_namespace_dependency.ts +1 -1
  66. package/src/state_machine/ua_two_state_variable.ts +14 -8
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { assert } from "node-opcua-assert";
5
5
  import { DataType, Variant, VariantArrayType } from "node-opcua-variant";
6
- import { coerceInt32, coerceInt64toInt32, coerceUInt64, Int32, Int64, isValidUInt64 } from "node-opcua-basic-types";
6
+ import { coerceInt32, coerceInt64toInt32, coerceUInt64, coerceUInt64toInt32, Int32, Int64, isValidInt64, isValidUInt64 } from "node-opcua-basic-types";
7
7
  import { coerceLocalizedText, LocalizedText, QualifiedNameLike } from "node-opcua-data-model";
8
8
  import { DataValue, DataValueT } from "node-opcua-data-value";
9
9
  import { StatusCodes } from "node-opcua-status-code";
@@ -12,26 +12,68 @@ import { NumericRange } from "node-opcua-numeric-range";
12
12
  import { DTEnumValue } from "node-opcua-nodeset-ua";
13
13
  import { BindVariableOptions, INamespace, UAVariable, UAProperty, ISessionContext } from "node-opcua-address-space-base";
14
14
  import { VariableTypeIds } from "node-opcua-constants";
15
+ import { _getBasicDataType, _getBasicDataTypeFromDataTypeNodeId } from "../get_basic_datatype";
15
16
 
16
17
  import { registerNodePromoter } from "../../source/loader/register_node_promoter";
17
18
  import { coerceEnumValues } from "../../source/helpers/coerce_enum_value";
18
19
  import { UAMultiStateValueDiscreteEx } from "../../source/interfaces/data_access/ua_multistate_value_discrete_ex";
19
20
  import { AddMultiStateValueDiscreteOptions } from "../../source/address_space_ts";
21
+ import { ISetStateOptions } from "../../source/interfaces/i_set_state_options";
20
22
  import { UAVariableImpl } from "../ua_variable_impl";
21
23
 
22
24
  import { add_dataItem_stuff } from "./add_dataItem_stuff";
23
25
 
24
- function install_synchronization<T, DT extends DataType>(variable: UAMultiStateValueDiscreteEx<T, DT>) {
26
+ function convertToArray<T>(array: any): T[] {
27
+ if (Array.isArray(array)) return array;
28
+ const result: T[] = [];
29
+ for (let i = 0; i < array.length; i++) {
30
+ result[i] = array[i];
31
+ }
32
+ return result;
33
+ }
34
+ const getCoerceToInt32 = (dataType: DataType) => {
35
+ switch (dataType) {
36
+ case DataType.UInt64:
37
+ return coerceUInt64toInt32;
38
+ case DataType.Int64:
39
+ return coerceInt64toInt32;
40
+ default:
41
+ return coerceInt32;
42
+ }
43
+ };
44
+
45
+ function install_synchronization<T extends number | Int64 | Int64, DT extends DataType>(
46
+ variable: UAMultiStateValueDiscreteEx<T, DT>
47
+ ) {
25
48
  const _variable = variable as UAMultiStateValueDiscreteEx<T, DT>;
26
- _variable.on("value_changed", (value: DataValue) => {
49
+ _variable.on("value_changed", (dataValue: DataValue) => {
27
50
  const valueAsTextNode = variable.valueAsText || (_variable.getComponentByName("ValueAsText") as UAVariable);
28
51
  if (!valueAsTextNode) {
29
52
  return;
30
53
  }
31
- const valueAsText1 = _variable.findValueAsText(value.value.value);
32
- valueAsTextNode.setValueFromSource(valueAsText1);
54
+ if (dataValue.value.arrayType === VariantArrayType.Array || dataValue.value.arrayType === VariantArrayType.Matrix) {
55
+ //
56
+ const coerce = getCoerceToInt32(_variable.getBasicDataType());
57
+
58
+ const values: number[] = convertToArray<Int32>(dataValue.value.value).map((a) => coerceInt32(a));
59
+ const variantArray: Variant[] = values.map((a) => _variable.findValueAsText(a));
60
+ const localizedText = variantArray.map((a) => a.value);
61
+
62
+ const valueAsText1 = new Variant({
63
+ arrayType: dataValue.value.arrayType,
64
+ dataType: DataType.LocalizedText,
65
+ value: localizedText,
66
+ dimensions: dataValue.value.dimensions
67
+ });
68
+ valueAsTextNode.setValueFromSource(valueAsText1);
69
+ } else {
70
+ const valueAsText1 = _variable.findValueAsText(dataValue.value.value);
71
+ valueAsTextNode.setValueFromSource(valueAsText1);
72
+ }
33
73
  });
34
- _variable.emit("value_changed", _variable.readValue());
74
+ const dataValue = _variable.readValue();
75
+ // detect value changes to update valueAsText (initial state)
76
+ _variable.emit("value_changed", dataValue);
35
77
  }
36
78
 
37
79
  export interface UAMultiStateValueDiscreteImpl<T, DT extends DataType> {
@@ -46,8 +88,11 @@ export interface UAMultiStateValueDiscreteImpl<T, DT extends DataType> {
46
88
 
47
89
  readValueAsync(context: ISessionContext | null, callback?: any): any;
48
90
  }
49
- export class UAMultiStateValueDiscreteImpl<T, DT extends DataType> extends UAVariableImpl implements UAMultiStateValueDiscreteEx<T, DT> {
50
- public setValue(value: string | number | Int64): void {
91
+ export class UAMultiStateValueDiscreteImpl<T, DT extends DataType>
92
+ extends UAVariableImpl
93
+ implements UAMultiStateValueDiscreteEx<T, DT>
94
+ {
95
+ public setValue(value: string | number | Int64, options?: ISetStateOptions): void {
51
96
  if (typeof value === "string") {
52
97
  const enumValues = this.enumValues.readValue().value.value;
53
98
  const selected = enumValues.filter((a: any) => a.displayName.text === value)[0];
@@ -57,16 +102,20 @@ export class UAMultiStateValueDiscreteImpl<T, DT extends DataType> extends UAVar
57
102
  throw new Error("cannot find enum string " + value + " in " + enumValues.toString());
58
103
  }
59
104
  } else {
60
- this._setValue(coerceUInt64(value));
105
+ this._setValue(coerceUInt64(value), options);
61
106
  }
62
107
  }
63
108
 
64
- public getValueAsString(): string {
65
- return this.valueAsText.readValue().value.value.text || "";
109
+ public getValueAsString(): any {
110
+ const v = this.valueAsText.readValue().value.value;
111
+ if (Array.isArray(v)) {
112
+ return v.map((a) => a.text);
113
+ }
114
+ return v.text || "";
66
115
  }
67
116
 
68
- public getValueAsNumber(): number {
69
- return this.readValue().value.value as unknown as number;
117
+ public getValueAsNumber(): any {
118
+ return this.readValue().value.value;
70
119
  }
71
120
 
72
121
  public checkVariantCompatibility(value: Variant): StatusCode {
@@ -89,7 +138,7 @@ export class UAMultiStateValueDiscreteImpl<T, DT extends DataType> extends UAVar
89
138
  public _isValueInRange(value: number): boolean {
90
139
  // MultiStateValueDiscreteType
91
140
  const enumValues = this.enumValues.readValue().value.value as DTEnumValue[];
92
- const e = enumValues.findIndex((x: DTEnumValue) => coerceInt32(x.value) === value);
141
+ const e = enumValues.findIndex((x: DTEnumValue) => coerceInt64toInt32(x.value) === value);
93
142
  return !(e === -1);
94
143
  }
95
144
  /**
@@ -114,18 +163,18 @@ export class UAMultiStateValueDiscreteImpl<T, DT extends DataType> extends UAVar
114
163
  *
115
164
  * @private
116
165
  */
117
- public _setValue(value: Int64): void {
166
+ public _setValue(value: Int64, options?: ISetStateOptions): void {
167
+ const int32Value = coerceInt64toInt32(value);
118
168
  // check that value is in bound
119
- if (!this._isValueInRange(coerceInt32(value))) {
169
+ if (!this._isValueInRange(int32Value)) {
120
170
  throw new Error("UAMultiStateValueDiscrete#_setValue out of range " + value);
121
171
  }
122
172
 
123
173
  const dataType = this._getDataType();
124
174
  if (dataType === DataType.Int64 || dataType === DataType.UInt64) {
125
- this.setValueFromSource({ dataType, value });
175
+ this.setValueFromSource({ dataType, arrayType: VariantArrayType.Scalar, value });
126
176
  } else {
127
- const valueN = value[1];
128
- this.setValueFromSource({ dataType, value: valueN });
177
+ this.setValueFromSource({ dataType, arrayType: VariantArrayType.Scalar, value: int32Value });
129
178
  }
130
179
  }
131
180
 
@@ -135,17 +184,14 @@ export class UAMultiStateValueDiscreteImpl<T, DT extends DataType> extends UAVar
135
184
  */
136
185
  public findValueAsText(value?: number | Int64): Variant {
137
186
  const enumValueIndex = this._enumValueIndex();
138
-
139
187
  if (value === undefined) {
140
188
  throw new Error("Unexpected undefined value");
141
189
  }
142
- if (value instanceof Array) {
143
- value = value[1];
144
- }
145
- assert(!((value as any) instanceof Variant));
190
+ const valueAsInt32 = coerceInt64toInt32(value);
191
+
146
192
  let valueAsText1 = "Invalid";
147
- if (enumValueIndex[value]) {
148
- valueAsText1 = enumValueIndex[value].displayName.text || `Invalid:${value}`;
193
+ if (enumValueIndex[valueAsInt32] !== undefined) {
194
+ valueAsText1 = enumValueIndex[valueAsInt32].displayName.text || `Invalid:${value}`;
149
195
  }
150
196
  const result = new Variant({
151
197
  dataType: DataType.LocalizedText,
@@ -153,6 +199,7 @@ export class UAMultiStateValueDiscreteImpl<T, DT extends DataType> extends UAVar
153
199
  });
154
200
  return result;
155
201
  }
202
+
156
203
  public _getDataType(): DataType {
157
204
  if (this.dataType.value === 26 /* Number */) {
158
205
  return DataType.UInt32;
@@ -170,7 +217,7 @@ export class UAMultiStateValueDiscreteImpl<T, DT extends DataType> extends UAVar
170
217
  // this includes signed and unsigned integers from 8 to 64 Bit length.
171
218
 
172
219
  // istanbul ignore next
173
- validateDataType(this.dataType.value);
220
+ validateIsNumericDataType(this.dataType.value);
174
221
 
175
222
  // find the enum value type
176
223
  install_synchronization(this);
@@ -212,30 +259,33 @@ export function _addMultiStateValueDiscrete<T, DT extends DataType>(
212
259
  if (options.value === undefined && enumValues[0]) {
213
260
  options.value = enumValues[0].value; // Int64
214
261
  }
262
+ // Only DataTypes that can be represented with EnumValues are allowed for Variables of MultiStateValueDiscreteType.
263
+ // These are Integers up to 64 Bits (signed and unsigned).:
264
+
265
+ const dataType: DataType = _getBasicDataTypeFromDataTypeNodeId(addressSpace, options.dataType || DataType.UInt32);
266
+
215
267
  let value: undefined | BindVariableOptions;
216
- if (typeof options.value === "number" || isValidUInt64(options.value as number | number[])) {
217
- if (isValidUInt64(options.value as number | number[])) {
218
- value = new Variant({
219
- dataType: DataType.UInt32,
220
- value: (options.value as Int64)[1] // Low word
221
- });
222
- } else {
223
- value = new Variant({
224
- dataType: DataType.UInt32,
225
- value: options.value
226
- });
227
- }
268
+ if (
269
+ typeof options.value === "number" ||
270
+ isValidUInt64(options.value as number | number[]) ||
271
+ isValidInt64(options.value as number | number[])
272
+ ) {
273
+ value = new Variant({
274
+ dataType,
275
+ value: options.value
276
+ });
228
277
  } else {
229
278
  value = options.value as any;
230
279
  }
231
280
 
232
281
  const cloned_options = {
233
282
  ...options,
234
- dataType: DataType.UInt32,
283
+ dataType,
235
284
  typeDefinition: multiStateValueDiscreteType.nodeId,
236
285
  // valueRank:
237
286
  // note : OPCUA Spec 1.03 specifies -1:Scalar (part 8 page 8) but nodeset file specifies -2:Any
238
287
  value,
288
+ // limitation: although the Specs specify -2:any, we only support -1(Scalar)
239
289
  valueRank: -1 // -1 : Scalar
240
290
  };
241
291
 
@@ -267,6 +317,8 @@ export function _addMultiStateValueDiscrete<T, DT extends DataType>(
267
317
  minimumSamplingInterval: 0,
268
318
  modellingRule: options.modellingRule ? "Mandatory" : undefined,
269
319
  propertyOf: variable,
320
+ arrayDimensions: options.arrayDimensions,
321
+ valueRank: options.valueRank,
270
322
  typeDefinition: "PropertyType",
271
323
  userAccessLevel: "CurrentRead"
272
324
  // value: valueAsText
@@ -282,21 +334,23 @@ export function _addMultiStateValueDiscrete<T, DT extends DataType>(
282
334
  return variable;
283
335
  }
284
336
 
285
- export function validateDataType(dataTypeValue: any): void {
286
- const validTypes = [
287
- DataType.UInt64,
288
- DataType.Int64,
289
- DataType.UInt32,
290
- DataType.Int32,
291
- DataType.UInt16,
292
- DataType.Int16,
293
- DataType.Byte,
294
- DataType.Byte,
295
- DataType.SByte,
296
- 26 /*Number*/
297
- ];
298
-
299
- if (typeof dataTypeValue !== "number" || validTypes.indexOf(dataTypeValue) < 0) {
337
+ const validBasicNumericDataTypes = [
338
+ DataType.UInt64,
339
+ DataType.Int64,
340
+ DataType.UInt32,
341
+ DataType.Int32,
342
+ DataType.UInt16,
343
+ DataType.Int16,
344
+ DataType.Byte,
345
+ DataType.Byte,
346
+ DataType.SByte,
347
+ 26 /*Number*/
348
+ ];
349
+ export function validateIsNumericDataType(dataTypeValue: any): void {
350
+ if (typeof dataTypeValue !== "number" || validBasicNumericDataTypes.indexOf(dataTypeValue) < 0) {
300
351
  throw new Error(`Invalid DataType in UAMultiStateValueDiscrete => ${dataTypeValue.toString()}`);
301
352
  }
302
353
  }
354
+
355
+ /** @deprecated: use validateIsNumericDataType instead */
356
+ export const validateDataType = validateIsNumericDataType;
@@ -10,9 +10,11 @@ import { UAVariableImpl } from "../ua_variable_impl";
10
10
  import { registerNodePromoter } from "../../source/loader/register_node_promoter";
11
11
  import { AddTwoStateDiscreteOptions } from "../../source/address_space_ts";
12
12
  import { UATwoStateDiscreteEx } from "../../source/interfaces/data_access/ua_two_state_discrete_ex";
13
+ import { ISetStateOptions } from "../../source/interfaces/i_set_state_options";
13
14
 
14
15
  import { add_dataItem_stuff } from "./add_dataItem_stuff";
15
16
 
17
+
16
18
  export interface UATwoStateDiscreteImpl {
17
19
  falseState: UAProperty<LocalizedText, /*c*/ DataType.LocalizedText>;
18
20
  trueState: UAProperty<LocalizedText, /*c*/ DataType.LocalizedText>;
@@ -58,15 +60,15 @@ export class UATwoStateDiscreteImpl extends UAVariableImpl implements UATwoState
58
60
  );
59
61
  }
60
62
  }
61
- setValue(value: boolean | LocalizedTextLike): void {
63
+ setValue(value: boolean | LocalizedTextLike, options?: ISetStateOptions): void {
62
64
  if (typeof value === "boolean") {
63
65
  this.setValueFromSource({ dataType: DataType.Boolean, value });
64
66
  } else {
65
67
  const text: string = (typeof value === "string" ? value : value.text) || "";
66
68
  if (text === this.getTrueStateAsString()) {
67
- this.setValue(true);
69
+ this.setValue(true, options);
68
70
  } else if (text === this.getFalseStateAsString()) {
69
- this.setValue(false);
71
+ this.setValue(false, options);
70
72
  } else {
71
73
  throw new Error("setValue invalid value " + value);
72
74
  }
@@ -1,7 +1,7 @@
1
1
  import { IAddressSpace } from "node-opcua-address-space-base";
2
2
  import { DataType } from "node-opcua-basic-types";
3
3
  import { NodeClass } from "node-opcua-data-model";
4
- import { NodeId } from "node-opcua-nodeid";
4
+ import { NodeId, NodeIdLike } from "node-opcua-nodeid";
5
5
 
6
6
  export interface IBaseNodeVariableOrVariableType {
7
7
  addressSpace: IAddressSpace;
@@ -10,6 +10,19 @@ export interface IBaseNodeVariableOrVariableType {
10
10
  interface IBaseNodeVariableOrVariableTypeEx extends IBaseNodeVariableOrVariableType {
11
11
  _basicDataType: DataType;
12
12
  }
13
+
14
+ export function _getBasicDataTypeFromDataTypeNodeId(
15
+ addressSpace: IAddressSpace,
16
+ dataTypeNodeId: { nodeId: NodeIdLike } | NodeIdLike
17
+ ): DataType {
18
+ const dataTypeNodeId_ = (dataTypeNodeId as any).nodeId ? (dataTypeNodeId as any).nodeId : dataTypeNodeId;
19
+ const dataTypeNode = addressSpace.findDataType(dataTypeNodeId_);
20
+ if (!dataTypeNode) {
21
+ return DataType.Null;
22
+ }
23
+ return dataTypeNode.getBasicDataType();
24
+ }
25
+
13
26
  export function _getBasicDataType(uaNode: IBaseNodeVariableOrVariableType): DataType {
14
27
  const _uaNode = uaNode as IBaseNodeVariableOrVariableTypeEx;
15
28
  if (_uaNode._basicDataType) {
@@ -23,10 +36,6 @@ export function _getBasicDataType(uaNode: IBaseNodeVariableOrVariableType): Data
23
36
  // may be node has been deleted already
24
37
  return DataType.Null;
25
38
  }
26
- const dataTypeNode = addressSpace.findDataType(_uaNode.dataType)!;
27
- const basicDataType =
28
- dataTypeNode && dataTypeNode.nodeClass === NodeClass.DataType ? dataTypeNode.getBasicDataType() : DataType.Null;
29
- // const basicDataType = addressSpace.findCorrespondingBasicDataType(uaNode.dataType);
30
- _uaNode._basicDataType = basicDataType;
31
- return basicDataType;
39
+ _uaNode._basicDataType = _getBasicDataTypeFromDataTypeNodeId(addressSpace, _uaNode.dataType);
40
+ return _uaNode._basicDataType;
32
41
  }
@@ -312,7 +312,7 @@ export function constructNamespacePriorityTable(addressSpace: IAddressSpace): {
312
312
  return { loadingOrder, priorityTable };
313
313
  }
314
314
 
315
- const doDebug = true;
315
+ const doDebug = false;
316
316
  export function constructNamespaceDependency(namespace: INamespace, priorityTable?: number[]): INamespace[] {
317
317
  const addressSpace = namespace.addressSpace;
318
318
  priorityTable = priorityTable || constructNamespacePriorityTable(addressSpace).priorityTable;
@@ -21,6 +21,8 @@ import { AddTwoStateVariableOptions } from "../../source/address_space_ts";
21
21
  import { UATwoStateVariableEx } from "../../source/ua_two_state_variable_ex";
22
22
  // private types
23
23
  import { UAVariableImpl, UAVariableImplT } from "../ua_variable_impl";
24
+ import { ISetStateOptions } from "../../source/interfaces/i_set_state_options";
25
+
24
26
 
25
27
  const hasTrueSubState_ReferenceTypeNodeId = resolveNodeId("HasTrueSubState");
26
28
  const hasFalseSubState_ReferenceTypeNodeId = resolveNodeId("HasFalseSubState");
@@ -54,19 +56,23 @@ const hasFalseSubState_ReferenceTypeNodeId = resolveNodeId("HasFalseSubState");
54
56
  // TwoStateVariableType
55
57
  // <StateIdentifier> Defined in Clause 5.4.3 Optional
56
58
 
57
- function _updateTransitionTime(node: UATwoStateVariableEx, _subState?: UAVariable) {
59
+ function _updateTransitionTime(node: UATwoStateVariableEx, _subState?: UAVariable, options?: ISetStateOptions) {
58
60
  // TransitionTime specifies the time when the current state was entered.
59
61
  if (node.transitionTime) {
60
- node.transitionTime.setValueFromSource({ dataType: DataType.DateTime, value: new Date() });
62
+ const transitionTime = options?.transitionTime || new Date();
63
+ node.transitionTime.setValueFromSource({ dataType: DataType.DateTime, value: transitionTime });
61
64
  }
62
65
  }
63
66
 
64
- function _updateEffectiveTransitionTime(node: UATwoStateVariableImpl) {
67
+ function _updateEffectiveTransitionTime(node: UATwoStateVariableImpl,options?: ISetStateOptions) {
65
68
  if (node.effectiveTransitionTime) {
69
+
70
+ const effectiveTransitionTime = options?.effectiveTransitionTime || new Date();
71
+
66
72
  // because subStateNode ",subStateNode.browseName.toString());
67
73
  node.effectiveTransitionTime.setValueFromSource({
68
74
  dataType: DataType.DateTime,
69
- value: new Date()
75
+ value: effectiveTransitionTime
70
76
  });
71
77
  }
72
78
  }
@@ -308,7 +314,7 @@ export class UATwoStateVariableImpl extends UAVariableImplT<LocalizedText, DataT
308
314
  * @method setValue
309
315
  * @param boolValue {Boolean}
310
316
  */
311
- public setValue(boolValue: boolean): void {
317
+ public setValue(boolValue: boolean, options?: ISetStateOptions): void {
312
318
  assert(typeof boolValue === "boolean");
313
319
  const dataValue = this.id!.readValue();
314
320
  const oldValue = dataValue.value.value;
@@ -317,8 +323,8 @@ export class UATwoStateVariableImpl extends UAVariableImplT<LocalizedText, DataT
317
323
  }
318
324
  //
319
325
  this.id.setValueFromSource(new Variant({ dataType: DataType.Boolean, value: boolValue }));
320
- _updateTransitionTime(this);
321
- _updateEffectiveTransitionTime(this);
326
+ _updateTransitionTime(this, undefined, options);
327
+ _updateEffectiveTransitionTime(this, options);
322
328
  }
323
329
 
324
330
  /**
@@ -369,7 +375,7 @@ export class UATwoStateVariableImpl extends UAVariableImplT<LocalizedText, DataT
369
375
  const addressSpace = this.addressSpace;
370
376
  // add event handle
371
377
  const subState = addressSpace.findNode(reference.nodeId) as UAVariable;
372
- subState.on("value_changed", _updateEffectiveTransitionTime.bind(null, this));
378
+ subState.on("value_changed", _updateEffectiveTransitionTime.bind(null, this, undefined));
373
379
  }
374
380
  }
375
381
  }