node-opcua-address-space 2.57.0 → 2.61.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.
Files changed (88) hide show
  1. package/dist/source/address_space_ts.d.ts +0 -2
  2. package/dist/source/helpers/argument_list.js +12 -1
  3. package/dist/source/helpers/argument_list.js.map +1 -1
  4. package/dist/source/helpers/multiform_func.d.ts +11 -0
  5. package/dist/source/helpers/multiform_func.js +74 -0
  6. package/dist/source/helpers/multiform_func.js.map +1 -0
  7. package/dist/source/loader/load_nodeset2.js +47 -64
  8. package/dist/source/loader/load_nodeset2.js.map +1 -1
  9. package/dist/source/set_namespace_meta_data.js +1 -1
  10. package/dist/src/address_space.js +12 -6
  11. package/dist/src/address_space.js.map +1 -1
  12. package/dist/src/alarms_and_conditions/condition_snapshot.js +3 -3
  13. package/dist/src/alarms_and_conditions/condition_snapshot.js.map +1 -1
  14. package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.js +2 -1
  15. package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.js.map +1 -1
  16. package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.js +1 -1
  17. package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.js.map +1 -1
  18. package/dist/src/alarms_and_conditions/ua_condition_impl.js +8 -6
  19. package/dist/src/alarms_and_conditions/ua_condition_impl.js.map +1 -1
  20. package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js +1 -1
  21. package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js.map +1 -1
  22. package/dist/src/base_node_impl.js +2 -0
  23. package/dist/src/base_node_impl.js.map +1 -1
  24. package/dist/src/base_node_private.d.ts +3 -3
  25. package/dist/src/base_node_private.js +198 -25
  26. package/dist/src/base_node_private.js.map +1 -1
  27. package/dist/src/event_data.js +1 -1
  28. package/dist/src/event_data.js.map +1 -1
  29. package/dist/src/namespace_impl.js +5 -5
  30. package/dist/src/namespace_impl.js.map +1 -1
  31. package/dist/src/nodeset_tools/nodeset_to_xml.js +15 -9
  32. package/dist/src/nodeset_tools/nodeset_to_xml.js.map +1 -1
  33. package/dist/src/nodeset_tools/typedictionary_to_xml.js +17 -10
  34. package/dist/src/nodeset_tools/typedictionary_to_xml.js.map +1 -1
  35. package/dist/src/reference_impl.js +1 -1
  36. package/dist/src/reference_impl.js.map +1 -1
  37. package/dist/src/state_machine/ua_shelving_state_machine_ex.js +20 -13
  38. package/dist/src/state_machine/ua_shelving_state_machine_ex.js.map +1 -1
  39. package/dist/src/ua_data_type_impl.d.ts +15 -5
  40. package/dist/src/ua_data_type_impl.js +129 -51
  41. package/dist/src/ua_data_type_impl.js.map +1 -1
  42. package/dist/src/ua_method_impl.d.ts +3 -2
  43. package/dist/src/ua_method_impl.js +7 -1
  44. package/dist/src/ua_method_impl.js.map +1 -1
  45. package/dist/src/ua_object_impl.js +2 -1
  46. package/dist/src/ua_object_impl.js.map +1 -1
  47. package/dist/src/ua_variable_impl.d.ts +12 -18
  48. package/dist/src/ua_variable_impl.js +285 -215
  49. package/dist/src/ua_variable_impl.js.map +1 -1
  50. package/dist/src/ua_variable_type_impl.d.ts +3 -4
  51. package/dist/src/ua_variable_type_impl.js +60 -52
  52. package/dist/src/ua_variable_type_impl.js.map +1 -1
  53. package/dist/src/ua_view_impl.js +1 -1
  54. package/dist/src/ua_view_impl.js.map +1 -1
  55. package/distHelpers/add_event_generator_object.js.map +1 -1
  56. package/distHelpers/mock_session.js +1 -1
  57. package/distHelpers/mock_session.js.map +1 -1
  58. package/package.json +35 -35
  59. package/source/address_space_ts.ts +0 -1
  60. package/source/helpers/argument_list.ts +13 -3
  61. package/source/helpers/multiform_func.ts +76 -0
  62. package/source/loader/load_nodeset2.ts +64 -80
  63. package/source/set_namespace_meta_data.ts +1 -1
  64. package/src/address_space.ts +16 -7
  65. package/src/alarms_and_conditions/condition_snapshot.ts +4 -4
  66. package/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.ts +7 -6
  67. package/src/alarms_and_conditions/ua_alarm_condition_impl.ts +2 -2
  68. package/src/alarms_and_conditions/ua_condition_impl.ts +29 -15
  69. package/src/alarms_and_conditions/ua_off_normal_alarm_impl.ts +1 -1
  70. package/src/base_node_impl.ts +3 -1
  71. package/src/base_node_private.ts +282 -36
  72. package/src/event_data.ts +1 -1
  73. package/src/namespace_impl.ts +6 -6
  74. package/src/nodeset_tools/nodeset_to_xml.ts +20 -10
  75. package/src/nodeset_tools/typedictionary_to_xml.ts +17 -7
  76. package/src/reference_impl.ts +3 -3
  77. package/src/state_machine/ua_shelving_state_machine_ex.ts +32 -19
  78. package/src/ua_data_type_impl.ts +168 -61
  79. package/src/ua_method_impl.ts +21 -7
  80. package/src/ua_object_impl.ts +10 -2
  81. package/src/ua_variable_impl.ts +419 -325
  82. package/src/ua_variable_type_impl.ts +86 -52
  83. package/src/ua_view_impl.ts +1 -1
  84. package/test_helpers/add_event_generator_object.ts +4 -3
  85. package/test_helpers/mock_session.ts +1 -1
  86. package/test_helpers/test_fixtures/fixture_simple_statemachine_nodeset2.xml +18 -0
  87. package/test_helpers/test_fixtures/fixuture_nodeset_objects_with_some_methods.xml +9 -1
  88. package/test_helpers/test_fixtures/mini.Node.Set2.xml +22 -1
@@ -34,12 +34,16 @@ import {
34
34
  CloneOptions
35
35
  } from "node-opcua-address-space-base";
36
36
  import { DataValue } from "node-opcua-data-value";
37
+ import { ObjectTypeIds, VariableTypeIds } from "node-opcua-constants";
37
38
 
38
39
  import { UANamespace_process_modelling_rule } from "./namespace_private";
39
40
  import { ReferenceImpl } from "./reference_impl";
40
41
  import { BaseNodeImpl, getReferenceType } from "./base_node_impl";
41
42
  import { AddressSpacePrivate } from "./address_space_private";
42
- import { UAObjectImpl } from "./ua_object_impl";
43
+
44
+ // eslint-disable-next-line prefer-const
45
+ let dotrace = false;
46
+ const traceLog = console.log.bind(console);
43
47
 
44
48
  const g_weakMap = new WeakMap();
45
49
 
@@ -184,7 +188,10 @@ export function BaseNode_References_toString(this: BaseNode, options: ToStringOp
184
188
  const addressSpace = this.addressSpace;
185
189
 
186
190
  options.add(
187
- options.padding + chalk.yellow(" references : ") + " length =" + Object.keys(_private._referenceIdx).length
191
+ options.padding +
192
+ chalk.yellow(" references : ") +
193
+ " length =" +
194
+ Object.keys(_private._referenceIdx).length
188
195
  );
189
196
 
190
197
  function dump_reference(follow: boolean, reference: UAReference | null) {
@@ -193,8 +200,37 @@ export function BaseNode_References_toString(this: BaseNode, options: ToStringOp
193
200
  }
194
201
  const o = ReferenceImpl.resolveReferenceNode(addressSpace, reference);
195
202
  const name = o ? o.browseName.toString() : "<???>";
203
+ const extra =
204
+ (o.modellingRule || " ")[0] +
205
+ (() => {
206
+ switch (o.nodeClass) {
207
+ case NodeClass.Object:
208
+ return "[O] ";
209
+ case NodeClass.Variable:
210
+ return "[V] " + (o as UAVariable).dataType.toString(displayOptions).padEnd(10);
211
+ case NodeClass.Method:
212
+ return "[M] ";
213
+ case NodeClass.DataType:
214
+ return "[DT]";
215
+ case NodeClass.ReferenceType:
216
+ return "[RT]";
217
+ case NodeClass.ObjectType:
218
+ return "[OT]";
219
+ case NodeClass.VariableType:
220
+ return "[VT]";
221
+ case NodeClass.View:
222
+ return "[V] ";
223
+ }
224
+ return "";
225
+ })();
196
226
  options.add(
197
- options.padding + chalk.yellow(" +-> ") + reference.toString(displayOptions) + " " + chalk.cyan(name)
227
+ options.padding +
228
+ chalk.yellow(" +-> ") +
229
+ reference.toString(displayOptions) +
230
+ " " +
231
+ chalk.cyan(name.padEnd(25, " ")) +
232
+ " " +
233
+ chalk.magentaBright(extra)
198
234
  );
199
235
 
200
236
  // ignore HasTypeDefinition as it has been already handled
@@ -223,7 +259,7 @@ export function BaseNode_References_toString(this: BaseNode, options: ToStringOp
223
259
 
224
260
  options.add(
225
261
  options.padding +
226
- chalk.yellow(" back_references : ") +
262
+ chalk.yellow(" back_references : ") +
227
263
  chalk.cyan(" length =") +
228
264
  br.length +
229
265
  chalk.grey(" ( references held by other nodes involving this node)")
@@ -343,6 +379,10 @@ function AccessLevelFlags_toString(this: UAVariable, options: ToStringOption) {
343
379
  );
344
380
  }
345
381
  }
382
+
383
+ interface WithDataValue {
384
+ $dataValue?: DataValue;
385
+ }
346
386
  export function VariableOrVariableType_toString(this: UAVariableType | UAVariable, options: ToStringOption): void {
347
387
  assert(options);
348
388
  if (this.dataType) {
@@ -352,7 +392,7 @@ export function VariableOrVariableType_toString(this: UAVariableType | UAVariabl
352
392
  options.add(options.padding + chalk.yellow(" dataType : ") + this.dataType + " " + n);
353
393
  }
354
394
  if (this.nodeClass === NodeClass.Variable) {
355
- const _dataValue = (<any>this)._dataValue as DataValue | undefined;
395
+ const _dataValue = (<WithDataValue>this).$dataValue as DataValue | undefined;
356
396
  if (_dataValue) {
357
397
  options.add(
358
398
  options.padding +
@@ -392,6 +432,16 @@ export function VariableOrVariableType_toString(this: UAVariableType | UAVariabl
392
432
  }
393
433
  }
394
434
 
435
+ const defaultExtraInfo = {
436
+ level: 0,
437
+ pad(): string {
438
+ return "";
439
+ },
440
+ registerClonedObject(node: BaseNode, node1: BaseNode): void {
441
+ /** */
442
+ }
443
+ };
444
+
395
445
  /**
396
446
  * clone properties and methods
397
447
  * @private
@@ -400,17 +450,17 @@ function _clone_collection_new(
400
450
  newParent: BaseNode,
401
451
  collectionRef: UAReference[],
402
452
  copyAlsoModellingRules: boolean,
403
- optionalFilter?: CloneFilter,
404
- extraInfo?: CloneExtraInfo
453
+ optionalFilter: CloneFilter,
454
+ extraInfo: CloneExtraInfo,
455
+ browseNameMap: Set<string>
405
456
  ): void {
406
457
  const namespace = newParent.namespace;
407
-
458
+ extraInfo = extraInfo || defaultExtraInfo;
408
459
  const addressSpace = newParent.addressSpace;
409
460
  assert(!optionalFilter || (typeof optionalFilter.shouldKeep === "function" && typeof optionalFilter.filterFor === "function"));
410
461
 
411
462
  for (const reference of collectionRef) {
412
- const node: BaseNode = ReferenceImpl.resolveReferenceNode(addressSpace, reference);
413
-
463
+ const node = ReferenceImpl.resolveReferenceNode(addressSpace, reference) as UAVariable | UAObject | UAMethod;
414
464
  // ensure node is of the correct type,
415
465
  // it may happen that the xml nodeset2 file was malformed
416
466
 
@@ -429,18 +479,41 @@ function _clone_collection_new(
429
479
  }
430
480
 
431
481
  if (optionalFilter && node && !optionalFilter.shouldKeep(node)) {
482
+ dotrace && traceLog(extraInfo.pad(), "skipping ", node.browseName.toString());
432
483
  continue; // skip this node
433
484
  }
485
+ const key = node.browseName.toString();
486
+ if (browseNameMap?.has(key)) {
487
+ continue; // skipping node with same browseName
488
+ }
489
+ browseNameMap?.add(key);
434
490
 
435
- assert(reference.isForward);
436
- assert(reference.referenceType instanceof NodeId, "" + reference.referenceType.toString());
491
+ // assert(reference.isForward);
492
+ // assert(reference.referenceType instanceof NodeId, "" + reference.referenceType.toString());
437
493
  const options = {
438
494
  namespace,
439
495
  references: [new ReferenceImpl({ referenceType: reference.referenceType, isForward: false, nodeId: newParent.nodeId })],
440
496
  copyAlsoModellingRules
441
497
  };
442
498
 
499
+ dotrace &&
500
+ traceLog(
501
+ extraInfo.pad(),
502
+ "cloning => ",
503
+ reference.referenceType.toString({ addressSpace }),
504
+ "=>",
505
+ node.browseName.toString(),
506
+ chalk.magentaBright(node.typeDefinitionObj?.browseName.toString())
507
+ );
508
+
509
+ extraInfo.level += 4;
443
510
  const clone = (node as UAVariable | UAMethod | UAObject).clone(options, optionalFilter, extraInfo);
511
+ extraInfo.level -= 4;
512
+
513
+ // also clone or instantiate interface members that may be required in the optionals
514
+ extraInfo.level++;
515
+ _cloneInterface(newParent, node, optionalFilter, extraInfo, browseNameMap);
516
+ extraInfo.level--;
444
517
 
445
518
  if (extraInfo) {
446
519
  extraInfo.registerClonedObject(node, clone);
@@ -448,24 +521,179 @@ function _clone_collection_new(
448
521
  }
449
522
  }
450
523
 
451
- export function _clone_children_references(
452
- node: BaseNode,
524
+ type UAInterface = UAObjectType;
525
+ function _extractInterfaces2(typeDefinitionNode: UAObjectType | UAVariableType, extraInfo: CloneExtraInfo): UAInterface[] {
526
+ if (
527
+ !typeDefinitionNode ||
528
+ (typeDefinitionNode.nodeId.namespace === 0 &&
529
+ (typeDefinitionNode.nodeId.value === ObjectTypeIds.BaseObjectType ||
530
+ typeDefinitionNode.nodeId.value === VariableTypeIds.BaseVariableType))
531
+ ) {
532
+ return [];
533
+ }
534
+
535
+ const addressSpace = typeDefinitionNode.addressSpace;
536
+ // example:
537
+ // FolderType
538
+ // FunctionalGroupType
539
+ // MachineryItemIdentificationType : IMachineryItemVendorNameplateType
540
+ // MachineIdentificationType : IMachineTagNameplateType, IMachineVendorNamePlateType
541
+ // MachineToolIdentificationType
542
+ //
543
+ //
544
+ // IMachineTagNameplateType -subTypeOf-> ITagNameplateType
545
+ // IMachineVendorNamePlateType -subTypeOf-> IMachineryItemVendorNamePlateType
546
+ // IMachineryItemVendorNamePlateType -subTypeOf-> IVendorNameplateType
547
+ const interfacesRef = typeDefinitionNode.findReferencesEx("HasInterface", BrowseDirection.Forward);
548
+ const interfaces = interfacesRef.map((r) => addressSpace.findNode(r.nodeId) as UAInterface);
549
+
550
+ const baseInterfaces: UAInterface[] = [];
551
+ for (const iface of interfaces) {
552
+ dotrace &&
553
+ traceLog(
554
+ extraInfo.pad(),
555
+ typeDefinitionNode.browseName.toString(),
556
+ " - has interface -> ",
557
+ iface.browseName.toString()
558
+ );
559
+ baseInterfaces.push(iface);
560
+ if (iface.subtypeOfObj) {
561
+ extraInfo.level++;
562
+ baseInterfaces.push(..._extractInterfaces2(iface.subtypeOfObj, extraInfo));
563
+ extraInfo.level--;
564
+ }
565
+ }
566
+ interfaces.push(...baseInterfaces);
567
+ if (typeDefinitionNode.subtypeOfObj) {
568
+ dotrace &&
569
+ traceLog(
570
+ extraInfo.pad(),
571
+ typeDefinitionNode.browseName.toString(),
572
+ " - subtypef -> ",
573
+ typeDefinitionNode.subtypeOfObj.browseName.toString()
574
+ );
575
+ extraInfo.level++;
576
+ interfaces.push(..._extractInterfaces2(typeDefinitionNode.subtypeOfObj, extraInfo));
577
+ extraInfo.level--;
578
+ }
579
+ const dedupedInterfaces = [...new Set(interfaces)];
580
+
581
+ dotrace &&
582
+ traceLog(
583
+ extraInfo.pad(),
584
+ chalk.yellow("Interface for ", typeDefinitionNode.browseName.toString()),
585
+ "=",
586
+ dedupedInterfaces.map((x) => x.browseName.toString()).join(" ")
587
+ );
588
+ return dedupedInterfaces;
589
+ }
590
+
591
+ /*
592
+
593
+ // also find all related interfaces
594
+ if (false && typeDefinitionNode) {
595
+ dotrace && tracelog("typeDefinitionNode = ", typeDefinitionNode.browseName.toString());
596
+ const interfaces = _extractInterfaces(typeDefinitionNode);
597
+ for (const interfaceNode of interfaces) {
598
+ dotrace && tracelog(" adding member of interface ", interfaceNode.browseName.toString());
599
+ const fromInterface = interfaceNode.findReferencesEx("Aggregates", BrowseDirection.Forward);
600
+ dotrace && tracelog(
601
+ " B ",
602
+ fromInterface.map((r) => r.toString({ addressSpace }) + " " + r.node!.browseName.toString()).join("\n")
603
+ );
604
+ add(fromInterface);
605
+ }
606
+ }
607
+ */
608
+
609
+ function _crap_extractInterfaces(typeDefinitionNode: UAObjectType | UAVariableType, extraInfo: CloneExtraInfo): UAInterface[] {
610
+ if (
611
+ typeDefinitionNode.nodeId.namespace === 0 &&
612
+ (typeDefinitionNode.nodeId.value === ObjectTypeIds.BaseObjectType ||
613
+ typeDefinitionNode.nodeId.value === VariableTypeIds.BaseVariableType)
614
+ ) {
615
+ return [];
616
+ }
617
+
618
+ const addressSpace = typeDefinitionNode.addressSpace;
619
+ // example:
620
+ // FolderType
621
+ // FunctionalGroupType
622
+ // MachineryItemIdentificationType : IMachineryItemVendorNameplateType
623
+ // MachineIdentificationType : IMachineTagNameplateType, IMachineVendorNamePlateType
624
+ // MachineToolIdentificationType
625
+ //
626
+ //
627
+ // IMachineTagNameplateType -subTypeOf-> ITagNameplateType
628
+ // IMachineVendorNamePlateType -subTypeOf-> IMachineryItemVendorNamePlateType
629
+ // IMachineryItemVendorNamePlateType -subTypeOf-> IVendorNameplateType
630
+ const interfacesRef = typeDefinitionNode.findReferencesEx("HasInterface", BrowseDirection.Forward);
631
+ const interfaces = interfacesRef.map((r) => r.node! as UAInterface);
632
+ for (const iface of interfaces) {
633
+ dotrace && traceLog(extraInfo.pad(), " interface ", iface.browseName.toString());
634
+ }
635
+
636
+ return interfaces;
637
+ }
638
+
639
+ function _cloneInterface(
453
640
  newParent: BaseNode,
641
+ node: UAObject | UAVariable | UAMethod,
642
+ optionalFilter: CloneFilter,
643
+ extraInfo: CloneExtraInfo,
644
+ browseNameMap: Set<string>
645
+ ): void {
646
+ dotrace &&
647
+ traceLog(
648
+ extraInfo?.pad(),
649
+ chalk.green("-------------------- now cloning interfaces of ", node.browseName.toString(), node.nodeId.toString())
650
+ );
651
+
652
+ extraInfo = extraInfo || defaultExtraInfo;
653
+ const addressSpace = node.addressSpace;
654
+ const typeDefinitionNode = node.typeDefinitionObj;
655
+ if (!typeDefinitionNode) {
656
+ return;
657
+ }
658
+ dotrace && traceLog(extraInfo.pad(), " --- {");
659
+ const interfaces = _extractInterfaces2(typeDefinitionNode, extraInfo);
660
+ dotrace && traceLog(extraInfo.pad(), " --- }");
661
+ dotrace && traceLog(extraInfo?.pad(), chalk.green("-------------------- interfaces are ", interfaces.length));
662
+
663
+ const localFilter = optionalFilter.filterFor(node);
664
+
665
+ for (const iface of interfaces) {
666
+ const aggregates = iface.findReferencesEx("Aggregates", BrowseDirection.Forward);
667
+ dotrace &&
668
+ traceLog(
669
+ extraInfo.pad(),
670
+ chalk.magentaBright(" interface ", iface.browseName.toString()),
671
+ "\n" + extraInfo?.pad(),
672
+ aggregates.map((r) => r.toString({ addressSpace })).join("\n" + extraInfo?.pad())
673
+ );
674
+ _clone_collection_new(newParent, aggregates, false, localFilter, extraInfo, browseNameMap);
675
+ }
676
+ }
677
+ export function _clone_children_references(
678
+ node: UAObject | UAVariable | UAMethod | UAObjectType | UAVariableType,
679
+ newParent: UAObject | UAVariable | UAMethod,
454
680
  copyAlsoModellingRules: boolean,
455
- optionalFilter?: CloneFilter,
456
- extraInfo?: CloneExtraInfo
681
+ optionalFilter: CloneFilter,
682
+ extraInfo: CloneExtraInfo,
683
+ browseNameMap: Set<string>
457
684
  ): void {
458
685
  // find all reference that derives from the Aggregates
459
686
  const aggregatesRef = node.findReferencesEx("Aggregates", BrowseDirection.Forward);
460
- _clone_collection_new(newParent, aggregatesRef, copyAlsoModellingRules, optionalFilter, extraInfo);
687
+ _clone_collection_new(newParent, aggregatesRef, copyAlsoModellingRules, optionalFilter, extraInfo, browseNameMap);
461
688
  }
462
689
 
463
690
  export function _clone_non_hierarchical_references(
464
691
  node: BaseNode,
465
692
  newParent: BaseNode,
466
693
  copyAlsoModellingRules: boolean,
467
- optionalFilter?: CloneFilter,
468
- extraInfo?: CloneExtraInfo
694
+ optionalFilter: CloneFilter,
695
+ extraInfo: CloneExtraInfo,
696
+ browseNameMap: Set<string>
469
697
  ): void {
470
698
  // clone only some non hierarchical_references that we do want to clone
471
699
  // such as:
@@ -474,7 +702,7 @@ export function _clone_non_hierarchical_references(
474
702
  assert(newParent instanceof BaseNodeImpl);
475
703
  // find all reference that derives from the HasSubStateMachine
476
704
  const references = node.findReferencesEx("HasSubStateMachine", BrowseDirection.Forward);
477
- _clone_collection_new(newParent, references, copyAlsoModellingRules, optionalFilter, extraInfo);
705
+ _clone_collection_new(newParent, references, copyAlsoModellingRules, optionalFilter, extraInfo, browseNameMap);
478
706
  }
479
707
 
480
708
  /**
@@ -485,8 +713,8 @@ export function _clone<T extends UAObject | UAVariable | UAMethod>(
485
713
  this: T,
486
714
  Constructor: new (options: any) => T,
487
715
  options: CloneOptions,
488
- optionalFilter?: CloneFilter,
489
- extraInfo?: CloneExtraInfo
716
+ optionalFilter: CloneFilter,
717
+ extraInfo: CloneExtraInfo
490
718
  ): T {
491
719
  assert(typeof Constructor === "function");
492
720
  assert(options !== null && typeof options === "object");
@@ -544,9 +772,31 @@ export function _clone<T extends UAObject | UAVariable | UAMethod>(
544
772
 
545
773
  options.copyAlsoModellingRules = options.copyAlsoModellingRules || false;
546
774
 
547
- const newFilter = optionalFilter ? optionalFilter.filterFor(cloneObj) : undefined;
548
- _clone_children_references(this, cloneObj, options.copyAlsoModellingRules, newFilter, extraInfo);
549
- _clone_non_hierarchical_references(this, cloneObj, options.copyAlsoModellingRules, newFilter, extraInfo);
775
+ const newFilter = optionalFilter.filterFor(cloneObj);
776
+
777
+ const browseNameMap = new Set<string>();
778
+ _clone_children_references(this, cloneObj, options.copyAlsoModellingRules, newFilter!, extraInfo, browseNameMap);
779
+
780
+ //
781
+ let typeDefinitionNode: UAVariableType | UAObjectType | null = this.typeDefinitionObj;
782
+ while (typeDefinitionNode) {
783
+ dotrace &&
784
+ traceLog(
785
+ extraInfo?.pad(),
786
+ chalk.blueBright("---------------------- Exploring ", typeDefinitionNode.browseName.toString())
787
+ );
788
+ _clone_children_references(
789
+ typeDefinitionNode,
790
+ cloneObj,
791
+ options.copyAlsoModellingRules,
792
+ newFilter,
793
+ extraInfo,
794
+ browseNameMap
795
+ );
796
+ typeDefinitionNode = typeDefinitionNode.subtypeOfObj;
797
+ }
798
+
799
+ _clone_non_hierarchical_references(this, cloneObj, options.copyAlsoModellingRules, newFilter, extraInfo, browseNameMap);
550
800
 
551
801
  cloneObj.propagate_back_references();
552
802
 
@@ -584,7 +834,7 @@ function _remove_HierarchicalReference(node: BaseNode, reference: UAReference) {
584
834
  if (referenceType.isSupertypeOf(HierarchicalReferencesType!)) {
585
835
  assert(reference.isForward);
586
836
  const targetNode = ReferenceImpl.resolveReferenceNode(addressSpace, reference);
587
- // Xx console.log(" adding object to map");
837
+ // Xx dotrace && tracelog(" adding object to map");
588
838
  delete _cache._childByNameMap[targetNode.browseName!.name!.toString()];
589
839
  }
590
840
  }
@@ -622,7 +872,7 @@ function _makeReferenceDescription(addressSpace: IAddressSpace, reference: UARef
622
872
  };
623
873
  }
624
874
  if (data.typeDefinition === null) {
625
- data.typeDefinition = NodeId.nullNodeId;
875
+ data.typeDefinition = new NodeId();
626
876
  }
627
877
  const referenceDescription = new ReferenceDescription(data);
628
878
  return referenceDescription;
@@ -665,18 +915,14 @@ export function BaseNode_add_backward_reference(this: BaseNode, reference: UARef
665
915
  // istanbul ignore next
666
916
  if (_private._back_referenceIdx[h]) {
667
917
  const opts = { addressSpace: this.addressSpace };
668
- // tslint:disable-next-line:no-console
669
- console.warn(" Warning !", this.browseName.toString());
670
- // tslint:disable-next-line:no-console
671
- console.warn(" ", reference.toString(opts));
672
- // tslint:disable-next-line:no-console
673
- console.warn(" already found in ===>");
674
- // tslint:disable-next-line:no-console
675
- console.warn(
918
+ warningLog(" Warning !", this.browseName.toString());
919
+ warningLog(" ", reference.toString(opts));
920
+ warningLog(" already found in ===>");
921
+ warningLog(
676
922
  (Object.values(_private._back_referenceIdx) as UAReference[]).map((c: UAReference) => c.toString(opts)).join("\n")
677
923
  );
678
924
  // tslint:disable-next-line:no-console
679
- console.warn("===>");
925
+ warningLog("===>");
680
926
  throw new Error("reference exists already in _back_references");
681
927
  }
682
928
 
package/src/event_data.ts CHANGED
@@ -25,7 +25,7 @@ export class EventData implements IEventData {
25
25
 
26
26
  constructor(eventTypeNode: BaseNode) {
27
27
  this.__nodes = {};
28
- this.eventId = NodeId.nullNodeId;
28
+ this.eventId = new NodeId();
29
29
  this.$eventDataSource = eventTypeNode;
30
30
  }
31
31
 
@@ -28,7 +28,7 @@ import {
28
28
  RolePermissionTypeOptions
29
29
  } from "node-opcua-types";
30
30
  import * as utils from "node-opcua-utils";
31
- import { DataType, Variant, VariantArrayType } from "node-opcua-variant";
31
+ import { DataType, Variant, VariantArrayType, verifyRankAndDimensions } from "node-opcua-variant";
32
32
  import {
33
33
  AddBaseNodeOptions,
34
34
  AddEnumerationTypeOptions,
@@ -100,7 +100,7 @@ import { _install_TwoStateVariable_machinery, _addTwoStateVariable } from "./sta
100
100
  //
101
101
  import { NamespacePrivate, UANamespace_process_modelling_rule } from "./namespace_private";
102
102
  import { BaseNodeImpl } from "./base_node_impl";
103
- import { UAVariableImpl, verifyRankAndDimensions } from "./ua_variable_impl";
103
+ import { UAVariableImpl } from "./ua_variable_impl";
104
104
 
105
105
  import { ConstructNodeIdOptions, NodeIdManager } from "./nodeid_manager";
106
106
  import { _addTwoStateDiscrete } from "./data_access/ua_two_state_discrete";
@@ -238,7 +238,7 @@ export class NamespaceImpl implements NamespacePrivate {
238
238
  }
239
239
 
240
240
  public getDefaultNamespace(): NamespacePrivate {
241
- return this.index === 0 ? this : (this.addressSpace.getDefaultNamespace());
241
+ return this.index === 0 ? this : this.addressSpace.getDefaultNamespace();
242
242
  }
243
243
 
244
244
  public dispose(): void {
@@ -656,7 +656,7 @@ export class NamespaceImpl implements NamespacePrivate {
656
656
  */
657
657
  public deleteNode(nodeOrNodeId: NodeId | BaseNode): void {
658
658
  let node: BaseNode | null = null;
659
- let nodeId: NodeId = NodeId.nullNodeId;
659
+ let nodeId: NodeId = new NodeId();
660
660
  if (nodeOrNodeId instanceof NodeId) {
661
661
  nodeId = nodeOrNodeId;
662
662
  node = this.findNode(nodeId);
@@ -1337,7 +1337,7 @@ export class NamespaceImpl implements NamespacePrivate {
1337
1337
  // or OptionSet DataType. It is derived from the DataType EnumValueType. If used for an
1338
1338
  // OptionSet, the corresponding Value in the base type contains the number of the bit associated
1339
1339
  // with the field. The EnumField is formally defined in Table 37.
1340
- (enumType as any).$definition = new EnumDefinition({
1340
+ (enumType as any).$fullDefinition = new EnumDefinition({
1341
1341
  fields: enumeration.map(
1342
1342
  (x: string, index: number) =>
1343
1343
  new EnumField({
@@ -1376,7 +1376,7 @@ export class NamespaceImpl implements NamespacePrivate {
1376
1376
  });
1377
1377
  assert(enumValues.browseName.toString() === "EnumValues");
1378
1378
 
1379
- (enumType as any).$definition = new EnumDefinition({
1379
+ (enumType as any).$fullDefinition = new EnumDefinition({
1380
1380
  fields: enumeration.map(
1381
1381
  (x: EnumerationItem, index: number) =>
1382
1382
  new EnumField({
@@ -592,7 +592,7 @@ function _dumpValue(xw: XmlWriter, node: UAVariable | UAVariableType, value: Var
592
592
 
593
593
  function _dumpArrayDimensionsAttribute(xw: XmlWriter, node: UAVariableType | UAVariable) {
594
594
  if (node.arrayDimensions) {
595
- if (node.arrayDimensions.length === 1 && node.arrayDimensions[0] === 0) {
595
+ if (node.valueRank === -1 || (node.arrayDimensions.length === 1 && node.arrayDimensions[0] === 0)) {
596
596
  return;
597
597
  }
598
598
  xw.writeAttribute("ArrayDimensions", node.arrayDimensions.join(","));
@@ -749,7 +749,11 @@ function _dumpEnumDefinition(xw: XmlWriter, enumDefinition: EnumDefinition) {
749
749
  xw.endElement();
750
750
  }
751
751
  }
752
- function _dumpStructureDefinition(xw: XmlWriter, structureDefinition: StructureDefinition) {
752
+ function _dumpStructureDefinition(
753
+ xw: XmlWriter,
754
+ structureDefinition: StructureDefinition,
755
+ baseStructureDefinition: StructureDefinition | null | undefined
756
+ ) {
753
757
  /*
754
758
  * note: baseDataType and defaultEncodingId are implicit and not stored in the XML file ??
755
759
  *
@@ -757,8 +761,12 @@ function _dumpStructureDefinition(xw: XmlWriter, structureDefinition: StructureD
757
761
  const baseDataType = structureDefinition.baseDataType;
758
762
  const defaultEncodingId = structureDefinition.defaultEncodingId;
759
763
 
760
- structureDefinition.fields = structureDefinition.fields || [];
761
- for (const defItem /*: StructureField*/ of structureDefinition.fields) {
764
+ // do not repeat elements that are already defined in base structure in the xml ouput!
765
+ const fields = structureDefinition.fields || [];
766
+ const nbFieldsInBase: number = baseStructureDefinition ? baseStructureDefinition.fields?.length || 0 : 0;
767
+
768
+ for(let index = nbFieldsInBase; index <fields.length; index++ ) {
769
+ const defItem = fields[index];
762
770
  xw.startElement("Field");
763
771
  xw.writeAttribute("Name", defItem.name!);
764
772
 
@@ -788,27 +796,29 @@ function _dumpStructureDefinition(xw: XmlWriter, structureDefinition: StructureD
788
796
  xw.endElement();
789
797
  }
790
798
  }
791
- function _dumpUADataTypeDefinition(xw: XmlWriter, node: UADataType) {
799
+ function _dumpUADataTypeDefinition(xw: XmlWriter, uaDataType: UADataType) {
792
800
  // to do remove DataType from base class
793
-
794
- const definition = node.getDefinition();
801
+ const uaDataTypeBase = uaDataType.subtypeOfObj;
802
+ const definition = uaDataType.getDefinition();
795
803
  if (!definition) {
796
804
  return;
797
805
  }
798
806
  if (definition instanceof EnumDefinition) {
799
807
  xw.startElement("Definition");
800
- xw.writeAttribute("Name", node.browseName.name!);
808
+ xw.writeAttribute("Name", uaDataType.browseName.name!);
801
809
  _dumpEnumDefinition(xw, definition);
802
810
  xw.endElement();
803
811
  return;
804
812
  }
805
813
  if (definition instanceof StructureDefinition) {
814
+ const baseDefinition = uaDataTypeBase ? (uaDataTypeBase.getDefinition() as StructureDefinition | null) : null;
815
+
806
816
  xw.startElement("Definition");
807
- xw.writeAttribute("Name", node.browseName.name!);
817
+ xw.writeAttribute("Name", uaDataType.browseName.name!);
808
818
  if (definition.structureType === StructureType.Union) {
809
819
  xw.writeAttribute("IsUnion", "true");
810
820
  }
811
- _dumpStructureDefinition(xw, definition);
821
+ _dumpStructureDefinition(xw, definition, baseDefinition);
812
822
  xw.endElement();
813
823
  return;
814
824
  }
@@ -44,6 +44,7 @@ function dumpDataTypeStructure(
44
44
  addressSpace: IAddressSpace,
45
45
  map: { [key: number]: string },
46
46
  structureDefinition: StructureDefinition,
47
+ structureDefinitionBase: StructureDefinition | undefined| null,
47
48
  name: string,
48
49
  doc?: string
49
50
  ): void {
@@ -56,8 +57,14 @@ function dumpDataTypeStructure(
56
57
  xw.text(doc);
57
58
  xw.endElement();
58
59
  }
60
+
61
+ const fields = structureDefinition.fields || [];
62
+ // get base class
63
+ const nbFieldsInBase = structureDefinitionBase? structureDefinitionBase.fields?.length || 0 : 0;
64
+
59
65
  let optionalsCount = 0;
60
- for (const f of structureDefinition.fields || []) {
66
+ for (let index = nbFieldsInBase; index < fields.length; index ++) {
67
+ const f= fields [index];
61
68
  if (f.isOptional) {
62
69
  xw.startElement("opc:Field");
63
70
  xw.writeAttribute("Name", f.name + "Specified");
@@ -90,7 +97,9 @@ function dumpDataTypeStructure(
90
97
  xw.endElement();
91
98
  }
92
99
  }
93
- for (const f of structureDefinition.fields || []) {
100
+ for (let index = nbFieldsInBase; index < fields.length; index ++) {
101
+ const f= fields [index];
102
+
94
103
  const isArray = f.valueRank > 0 && f.arrayDimensions?.length;
95
104
 
96
105
  if (isArray) {
@@ -124,12 +133,13 @@ function dumpDataTypeToBSD(xw: XmlWriter, dataType: UADataType, map: { [key: num
124
133
 
125
134
  const name: string = dataType.browseName.name!;
126
135
 
127
- const def = (<UADataTypeImpl>dataType)._getDefinition(false);
128
- if (def instanceof StructureDefinition) {
129
- dumpDataTypeStructure(xw, addressSpace, map, def, name);
136
+ const definition = dataType.getDefinition();
137
+ if (definition instanceof StructureDefinition) {
138
+ const structureDefinitionBase = dataType.subtypeOfObj?.getStructureDefinition();
139
+ dumpDataTypeStructure(xw, addressSpace, map, definition, structureDefinitionBase, name);
130
140
  }
131
- if (def instanceof EnumDefinition) {
132
- dumpEnumeratedType(xw, def, name);
141
+ if (definition instanceof EnumDefinition) {
142
+ dumpEnumeratedType(xw, definition, name);
133
143
  }
134
144
  }
135
145
 
@@ -53,9 +53,9 @@ function _w(str: string, width: number): string {
53
53
  return (str + " ").substr(0, width);
54
54
  }
55
55
 
56
- function _localCoerceToNodeID(nodeIdLike: string | NodeId | BaseNode) {
57
- if ((nodeIdLike as any).nodeId) {
58
- return (nodeIdLike as BaseNode).nodeId;
56
+ function _localCoerceToNodeID(nodeIdLike: string | NodeIdLike | { nodeId: NodeId }): NodeId {
57
+ if (Object.prototype.hasOwnProperty.call(nodeIdLike, "nodeId")) {
58
+ return (nodeIdLike as { nodeId: NodeId }).nodeId;
59
59
  }
60
60
  return coerceNodeId(nodeIdLike);
61
61
  }