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.
- package/dist/displayNodeElement.js +119 -99
- package/dist/displayNodeElement.js.map +1 -1
- package/dist/generate_markdown_doc.js +6 -1
- package/dist/generate_markdown_doc.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/to_graphivz.d.ts +14 -0
- package/dist/to_graphivz.js +283 -0
- package/dist/to_graphivz.js.map +1 -0
- package/package.json +21 -21
- package/source/displayNodeElement.ts +148 -111
- package/source/generate_markdown_doc.ts +16 -1
- package/source/index.ts +2 -0
- package/source/to_graphivz.ts +335 -0
- package/.mocharc.js +0 -13
|
@@ -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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
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
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
85
|
-
|
|
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
|
-
//
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
|
|
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
|
-
|
|
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 {
|