node-opcua-modeler 2.62.6 → 2.63.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.
@@ -4,7 +4,8 @@ import {
4
4
  UAObjectType,
5
5
  UAVariable,
6
6
  resolveReferenceNode,
7
- resolveReferenceType
7
+ resolveReferenceType,
8
+ UAVariableType
8
9
  } from "node-opcua-address-space";
9
10
  import { NodeClass } from "node-opcua-data-model";
10
11
  import { NodeId, resolveNodeId } from "node-opcua-nodeid";
@@ -38,141 +39,177 @@ export interface DisplayNodeOptions {
38
39
  format: "cli" | "markdown";
39
40
  }
40
41
 
41
- export function displayNodeElement(node: BaseNode, options?: DisplayNodeOptions): string {
42
- const head: string[] = ["ReferenceType", "NodeId", "BrowseName", "ModellingRule", "TypeDefinition", "DataType", "Value"];
43
- const table = new TableHelper(head);
44
-
45
- table.push(["BrowseName: ", { colSpan: 6, content: node.browseName.toString() }]);
46
-
47
- const superType = (node as UAObjectType).subtypeOfObj;
48
- if (superType) {
49
- table.push(["Base", superType.browseName.toString(), { colSpan: 6, content: node.browseName.toString() }]);
42
+ interface Data {
43
+ table: TableHelper;
44
+ node: BaseNode;
45
+ alreadyDumped: Record<string, any>;
46
+ descriptions: Description[];
47
+ }
48
+ interface Description {
49
+ description: string;
50
+ name: string;
51
+ type: string;
52
+ }
53
+ function dumpReference(data: Data, ref: UAReference, filter?: string) {
54
+ resolveReferenceNode(data.node.addressSpace, ref);
55
+ if (!ref.isForward) {
56
+ return;
50
57
  }
51
-
52
- if (node.description) {
53
- table.push(["Description", node.description.toString(), { colSpan: 6, content: node.browseName.toString() }]);
58
+ if (NodeId.sameNodeId(ref.referenceType, hasSubtypeNodeId)) {
59
+ return; // ignore forward HasSubtype
54
60
  }
61
+ // ignore subtype references
62
+ /* istanbul ignore next */
63
+ if (!ref.node) {
64
+ // tslint:disable-next-line: no-console
65
+ console.log(" Halt ", ref.toString({ addressSpace: data.node.addressSpace }));
66
+ return;
67
+ }
68
+ const dir = ref.isForward ? " " : " ";
69
+ const refNode = ref.node!;
55
70
 
56
- const alreadyDumped: any = {};
57
-
58
- const descriptions: any = [];
59
-
60
- function dumpReference(ref: UAReference, filter?: string) {
61
- resolveReferenceNode(node.addressSpace, ref);
62
- if (!ref.isForward) {
71
+ const refType = resolveReferenceType(data.node.addressSpace, ref);
72
+ if (filter) {
73
+ if (refType.browseName.toString() !== filter) {
63
74
  return;
64
75
  }
65
- if (NodeId.sameNodeId(ref.referenceType, hasSubtypeNodeId)) {
66
- return; // ignore forward HasSubtype
67
- }
68
- // ignore subtype references
69
- /* istanbul ignore next */
70
- if (!ref.node) {
71
- // tslint:disable-next-line: no-console
72
- console.log(" Halt ", ref.toString({ addressSpace: node.addressSpace }));
73
- return;
74
- }
75
- const dir = ref.isForward ? " " : " ";
76
- const refNode = ref.node!;
77
-
78
- const refType = resolveReferenceType(node.addressSpace, ref);
79
- if (filter) {
80
- if (refType.browseName.toString() !== filter) {
81
- return;
82
- }
76
+ }
77
+ if (data.alreadyDumped[refNode.nodeId.toString()]) {
78
+ return;
79
+ }
80
+ // xx const r = refNode.findReferencesAsObject("HasModellingRule", true);
81
+ const modelingRule = refNode.modellingRule || ""; // r[0] ? r[0].browseName.toString() : "/";
82
+
83
+ let value = "";
84
+ let dataType = "";
85
+ if (refNode.nodeClass === NodeClass.Variable) {
86
+ const v = refNode as UAVariable;
87
+
88
+ const val = v.readValue().value.value;
89
+ if (v.isExtensionObject()) {
90
+ // don't do anything
91
+ } else if (v.isEnumeration() && val !== null) {
92
+ const enumValue = v.readEnumValue();
93
+ value = enumValue.value + " (" + enumValue.name + ")";
94
+ } else if (val instanceof Date) {
95
+ value = val ? val.toUTCString() : "";
96
+ } else {
97
+ value = val ? val.toString() : "null";
83
98
  }
84
- if (alreadyDumped[refNode.nodeId.toString()]) {
85
- return;
99
+ const actualDataType = DataType[v.readValue().value.dataType];
100
+ const basicDataType = DataType[v.dataTypeObj.basicDataType];
101
+ dataType = v.dataTypeObj.browseName.toString();
102
+ if (basicDataType !== dataType) {
103
+ dataType = dataType + "(" + basicDataType + ")";
86
104
  }
87
- // xx const r = refNode.findReferencesAsObject("HasModellingRule", true);
88
- const modelingRule = refNode.modellingRule || ""; // r[0] ? r[0].browseName.toString() : "/";
89
-
90
- let value = "";
91
- let dataType = "";
92
- if (refNode.nodeClass === NodeClass.Variable) {
93
- const v = refNode as UAVariable;
94
-
95
- const val = v.readValue().value.value;
96
- if (v.isExtensionObject()) {
97
- // don't do anything
98
- } else if (v.isEnumeration() && val !== null) {
99
- const enumValue = v.readEnumValue();
100
- value = enumValue.value + " (" + enumValue.name + ")";
101
- } else if (val instanceof Date) {
102
- value = val ? val.toUTCString() : "";
103
- } else {
104
- value = val ? val.toString() : "null";
105
- }
106
- const actualDataType = DataType[v.readValue().value.dataType];
107
- const basicDataType = DataType[v.dataTypeObj.basicDataType];
108
- dataType = v.dataTypeObj.browseName.toString();
109
- if (basicDataType !== dataType) {
110
- dataType = dataType + "(" + basicDataType + ")";
111
- }
112
- // findBasicDataType(v.dataTypeObj);
105
+ // findBasicDataType(v.dataTypeObj);
106
+ }
107
+
108
+ const row = [
109
+ refType.browseName.toString() + dir + symbol(refNode.nodeClass),
110
+ refNode.nodeId.toString(),
111
+ refNode.browseName.toString(),
112
+ modelingRule,
113
+ (refNode as any).typeDefinitionObj ? (refNode as any).typeDefinitionObj.browseName.toString() : "",
114
+ dataType,
115
+ value
116
+ ];
117
+
118
+ data.table.push(row);
119
+
120
+ data.descriptions.push({
121
+ description: refNode.description ? refNode.description.toString() : "",
122
+ name: refNode.browseName.name!,
123
+ type: dataType
124
+ });
125
+ data.alreadyDumped[refNode.nodeId.toString()] = 1;
126
+ }
127
+ function dumpReferences(data: Data, _references: UAReference[]) {
128
+ // xx for (const ref of references) {
129
+ // xx dumpReference(ref, "HasSubtype");
130
+ // xx }
131
+ for (const ref of _references) {
132
+ dumpReference(data, ref, "HasTypeDefinition");
133
+ }
134
+ for (const ref of _references) {
135
+ dumpReference(data, ref, "HasEncoding");
136
+ }
137
+ for (const ref of _references) {
138
+ dumpReference(data, ref, "HasComponent");
139
+ }
140
+ for (const ref of _references) {
141
+ dumpReference(data, ref, "HasProperty");
142
+ }
143
+ for (const ref of _references) {
144
+ dumpReference(data, ref, "Organizes");
145
+ }
146
+ }
147
+ export function displayNodeElement(node: BaseNode, options?: DisplayNodeOptions): string {
148
+ const head: string[] = ["ReferenceType", "NodeId", "BrowseName", "ModellingRule", "TypeDefinition", "DataType", "Value"];
149
+
150
+ function createTable() {
151
+ const table = new TableHelper(head);
152
+ table.push(["BrowseName: ", { colSpan: 6, content: node.browseName.toString() }]);
153
+
154
+ const superType = (node as UAObjectType).subtypeOfObj;
155
+ if (superType) {
156
+ table.push(["Base", superType.browseName.toString(), { colSpan: 6, content: node.browseName.toString() }]);
113
157
  }
114
158
 
115
- const row = [
116
- refType.browseName.toString() + dir + symbol(refNode.nodeClass),
117
- refNode.nodeId.toString(),
118
- refNode.browseName.toString(),
119
- modelingRule,
120
- (refNode as any).typeDefinitionObj ? (refNode as any).typeDefinitionObj.browseName.toString() : "",
121
- dataType,
122
- value
123
- ];
124
-
125
- table.push(row);
126
-
127
- descriptions.push({
128
- description: refNode.description ? refNode.description.toString() : "",
129
- name: refNode.browseName.name!,
130
- type: dataType
131
- });
132
- alreadyDumped[refNode.nodeId.toString()] = 1;
159
+ if (node.description) {
160
+ table.push(["Description", node.description.toString(), { colSpan: 6, content: node.browseName.toString() }]);
161
+ }
162
+ return table;
133
163
  }
164
+
165
+ const table = createTable();
166
+
167
+ const alreadyDumped: Record<string, any> = {};
168
+
169
+ const descriptions: Description[] = [];
170
+
134
171
  const references = node.allReferences();
135
172
 
136
173
  const m = {};
137
174
 
138
- function dumpReferences(_references: UAReference[]) {
139
- // xx for (const ref of references) {
140
- // xx dumpReference(ref, "HasSubtype");
141
- // xx }
142
- for (const ref of _references) {
143
- dumpReference(ref, "HasTypeDefinition");
144
- }
145
- for (const ref of _references) {
146
- dumpReference(ref, "HasEncoding");
147
- }
148
- for (const ref of _references) {
149
- dumpReference(ref, "HasComponent");
150
- }
151
- for (const ref of _references) {
152
- dumpReference(ref, "HasProperty");
153
- }
154
- for (const ref of _references) {
155
- dumpReference(ref, "Organizes");
175
+ const data = { table, node, alreadyDumped, descriptions };
176
+ dumpReferences(data, references);
177
+
178
+ function toText(table: TableHelper) {
179
+ if (options && options.format === "markdown") {
180
+ return table.toMarkdownTable();
181
+ } else {
182
+ return table.toString();
156
183
  }
157
184
  }
158
- dumpReferences(references);
185
+
186
+ const str: string[] = [];
187
+ const tables: TableHelper[] = [];
188
+ tables.push(table);
189
+ str.push(toText(table));
190
+
191
+ const str2: string[] = [];
159
192
 
160
193
  // add property from base object/variable type
161
194
  if (node.nodeClass === NodeClass.ObjectType || node.nodeClass === NodeClass.VariableType) {
162
195
  const curNode = node;
163
196
 
164
- let subtypeOf = (curNode as UAObjectType).subtypeOfObj;
197
+ let subtypeOf = (curNode as UAObjectType | UAVariableType).subtypeOfObj;
165
198
  while (subtypeOf) {
199
+ data.table = createTable();
166
200
  table.push([subtypeOf.browseName.toString() + ":", "--", "--", "--"]);
167
201
  const references2 = subtypeOf.allReferences();
168
- dumpReferences(references2);
202
+ dumpReferences(data, references2);
203
+
204
+ str.push("<details>");
205
+ str.push("<summary>Base type: " + subtypeOf.browseName.toString() + "</summary>");
206
+ str.push("");
207
+ str.push(toText(table));
208
+ str.push("");
209
+ str2.push("</details>");
210
+
169
211
  subtypeOf = (subtypeOf as UAObjectType).subtypeOfObj;
170
212
  }
171
213
  }
172
-
173
- if (options && options.format === "markdown") {
174
- return table.toMarkdownTable();
175
- } else {
176
- return table.toString();
177
- }
214
+ return str.join("\n") + str2.join("\n");
178
215
  }
@@ -3,8 +3,10 @@ import { BaseNode, Namespace, UADataType, UAObjectType, UAReferenceType, UAVaria
3
3
  import { coerceUInt32 } from "node-opcua-basic-types";
4
4
  import { DataTypeDefinition, EnumDefinition, StructureDefinition, StructureField } from "node-opcua-types";
5
5
  import { DataType } from "node-opcua-variant";
6
+ import { object } from "underscore";
6
7
  import { displayNodeElement } from "./displayNodeElement";
7
8
  import { TableHelper } from "./tableHelper";
9
+ import { dumpClassHierachry, graphVizToPlantUml, opcuaToDot } from "./to_graphivz";
8
10
 
9
11
  interface NamespacePriv2 {
10
12
  nodeIterator(): IterableIterator<BaseNode>;
@@ -74,7 +76,7 @@ function dataTypeToMarkdown(dataType: UADataType): string {
74
76
  f.valueRank ? f.valueRank : "",
75
77
  f.maxStringLength ? f.maxStringLength : "",
76
78
  f.arrayDimensions ? f.arrayDimensions : "",
77
- f.description.text || ""
79
+ (f.description.text || "").replace(/\n/g, "<br>"),
78
80
  ]);
79
81
  }
80
82
  writer.writeLine(table.toMarkdownTable());
@@ -123,6 +125,11 @@ export async function buildDocumentation(namespace: Namespace, writer: IWriter):
123
125
  for (const objectType of namespacePriv._objectTypeIterator()) {
124
126
  writer.writeLine("\n\n### " + objectType.browseName.name!.toString());
125
127
  writer.writeLine(d(objectType));
128
+
129
+ writer.writeLine(graphVizToPlantUml(dumpClassHierachry(objectType, {showBaseType: true, depth: 2})));
130
+
131
+ writer.writeLine(graphVizToPlantUml(opcuaToDot(objectType)));
132
+
126
133
  // enumerate components
127
134
  writer.writeLine(displayNodeElement(objectType, { format: "markdown" }));
128
135
 
@@ -145,6 +152,12 @@ export async function buildDocumentation(namespace: Namespace, writer: IWriter):
145
152
  writer.writeLine("\n\n### " + variableType.browseName.name!.toString());
146
153
  writer.writeLine(d(variableType));
147
154
  writer.writeLine("");
155
+
156
+ writer.writeLine(graphVizToPlantUml(dumpClassHierachry(variableType, {showBaseType: true, depth: 2})));
157
+
158
+ writer.writeLine(graphVizToPlantUml(opcuaToDot(variableType)));
159
+
160
+
148
161
  // enumerate components
149
162
  writer.writeLine(displayNodeElement(variableType, { format: "markdown" }));
150
163
  for (const reference of variableType.allReferences()) {
@@ -155,3 +168,5 @@ export async function buildDocumentation(namespace: Namespace, writer: IWriter):
155
168
  }
156
169
  }
157
170
  }
171
+
172
+
package/source/index.ts CHANGED
@@ -6,6 +6,7 @@ export * from "./build_model_inner";
6
6
  export * from "./addExtensionObjectDataType";
7
7
  export * from "./symbol";
8
8
  export * from "./to_cvs";
9
+ export * from "./to_graphivz";
9
10
  export * from "./generate_markdown_doc";
10
11
  //
11
12
  export * from "node-opcua-address-space";
@@ -20,6 +21,7 @@ export * from "node-opcua-basic-types";
20
21
  export * from "node-opcua-constants";
21
22
  export * from "node-opcua-assert";
22
23
  export * from "node-opcua-service-translate-browse-path";
24
+
23
25
  export { MethodIds, DataTypeIds, ReferenceTypeIds, VariableIds, VariableTypeIds, ObjectTypeIds, ObjectIds } from "node-opcua-constants";
24
26
 
25
27
  export {