node-opcua-modeler 2.63.1 → 2.64.1

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 (51) hide show
  1. package/MyModel.NodeSet2.xml +125 -0
  2. package/dist/addExtensionObjectDataType.d.ts +21 -21
  3. package/dist/addExtensionObjectDataType.js +130 -130
  4. package/dist/buildModel.d.ts +16 -0
  5. package/dist/buildModel.js +91 -0
  6. package/dist/buildModel.js.map +1 -0
  7. package/dist/build_model_inner.d.ts +17 -17
  8. package/dist/build_model_inner.js +40 -40
  9. package/dist/display.d.ts +2 -0
  10. package/dist/display.js +96 -0
  11. package/dist/display.js.map +1 -0
  12. package/dist/displayNodeElement.d.ts +5 -5
  13. package/dist/displayNodeElement.js +191 -156
  14. package/dist/displayNodeElement.js.map +1 -1
  15. package/dist/dump_state_machine_to_graphviz.d.ts +6 -0
  16. package/dist/dump_state_machine_to_graphviz.js +120 -0
  17. package/dist/dump_state_machine_to_graphviz.js.map +1 -0
  18. package/dist/generate_markdown_doc.d.ts +6 -6
  19. package/dist/generate_markdown_doc.js +266 -155
  20. package/dist/generate_markdown_doc.js.map +1 -1
  21. package/dist/index.d.ts +24 -24
  22. package/dist/index.js +48 -48
  23. package/dist/promoteToMandatory.d.ts +8 -8
  24. package/dist/promoteToMandatory.js +97 -97
  25. package/dist/setNamespaceMetaData.d.ts +1 -1
  26. package/dist/setNamespaceMetaData.js +5 -5
  27. package/dist/symbol.d.ts +1 -1
  28. package/dist/symbol.js +2 -2
  29. package/dist/tableHelper.d.ts +9 -9
  30. package/dist/tableHelper.js +60 -60
  31. package/dist/to_cvs.d.ts +2 -2
  32. package/dist/to_cvs.js +11 -11
  33. package/dist/to_graphivz.d.ts +14 -13
  34. package/dist/to_graphivz.js +294 -235
  35. package/dist/to_graphivz.js.map +1 -1
  36. package/dist/types.d.ts +1 -1
  37. package/dist/types.js +2 -2
  38. package/distNodeJS/build_documentation_to_file.d.ts +2 -2
  39. package/distNodeJS/build_documentation_to_file.js +26 -26
  40. package/distNodeJS/build_model.d.ts +7 -7
  41. package/distNodeJS/build_model.js +21 -21
  42. package/distNodeJS/index.d.ts +5 -5
  43. package/distNodeJS/index.js +19 -19
  44. package/distNodeJS/symbol_cvs.d.ts +3 -3
  45. package/distNodeJS/symbol_cvs.js +63 -63
  46. package/examples/make_model.ts +4 -3
  47. package/package.json +19 -19
  48. package/source/displayNodeElement.ts +165 -112
  49. package/source/dump_state_machine_to_graphviz.ts +164 -0
  50. package/source/generate_markdown_doc.ts +217 -82
  51. package/source/to_graphivz.ts +129 -48
@@ -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";
@@ -37,142 +38,194 @@ const hasSubtypeNodeId = resolveNodeId("HasSubtype");
37
38
  export interface DisplayNodeOptions {
38
39
  format: "cli" | "markdown";
39
40
  }
41
+ function encodeXML(s: string) {
42
+ return s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
43
+ }
44
+ interface Data {
45
+ table: TableHelper;
46
+ node: BaseNode;
47
+ alreadyDumped: Record<string, any>;
48
+ descriptions: Description[];
49
+ }
50
+ interface Description {
51
+ description: string;
52
+ name: string;
53
+ type: string;
54
+ }
55
+ function dumpReference(data: Data, ref: UAReference, filter?: string) {
56
+ resolveReferenceNode(data.node.addressSpace, ref);
57
+ if (!ref.isForward) {
58
+ return;
59
+ }
60
+ if (NodeId.sameNodeId(ref.referenceType, hasSubtypeNodeId)) {
61
+ return; // ignore forward HasSubtype
62
+ }
63
+ // ignore subtype references
64
+ /* istanbul ignore next */
65
+ if (!ref.node) {
66
+ // tslint:disable-next-line: no-console
67
+ console.log(" Halt ", ref.toString({ addressSpace: data.node.addressSpace }));
68
+ return;
69
+ }
70
+ const dir = ref.isForward ? " " : " ";
71
+ const refNode = ref.node!;
72
+
73
+ const refType = resolveReferenceType(data.node.addressSpace, ref);
74
+ if (filter) {
75
+ if (refType.browseName.name !== filter) {
76
+ return;
77
+ }
78
+ }
79
+ const key = ref.nodeId.toString() + ref.referenceType.toString();
80
+ if (data.alreadyDumped[key]) {
81
+ return;
82
+ }
83
+ // xx const r = refNode.findReferencesAsObject("HasModellingRule", true);
84
+ const modelingRule = refNode.modellingRule || ""; // r[0] ? r[0].browseName.toString() : "/";
85
+
86
+ let value = "";
87
+ let dataType = "";
88
+ if (refNode.nodeClass === NodeClass.Variable) {
89
+ const v = refNode as UAVariable;
90
+
91
+ const val = v.readValue().value.value;
92
+ if (v.isExtensionObject()) {
93
+ // don't do anything
94
+ } else if (v.isEnumeration() && val !== null) {
95
+ const enumValue = v.readEnumValue();
96
+ value = enumValue.value + " (" + enumValue.name + ")";
97
+ } else if (val instanceof Date) {
98
+ value = val ? val.toUTCString() : "";
99
+ } else {
100
+ value = val ? val.toString() : "null";
101
+ }
102
+ const actualDataType = DataType[v.readValue().value.dataType];
103
+ const basicDataType = DataType[v.dataTypeObj.basicDataType];
104
+ dataType = v.dataTypeObj.browseName.toString();
105
+ if (basicDataType !== dataType) {
106
+ dataType = dataType + "(" + basicDataType + ")";
107
+ }
108
+ // findBasicDataType(v.dataTypeObj);
109
+ }
40
110
 
111
+ const row = [
112
+ refType.browseName.toString() + dir + symbol(refNode.nodeClass),
113
+ refNode.nodeId.toString(),
114
+ encodeXML(refNode.browseName.toString()),
115
+ modelingRule,
116
+ (refNode as any).typeDefinitionObj ? (refNode as any).typeDefinitionObj.browseName.toString() : "",
117
+ dataType,
118
+ value
119
+ ];
120
+
121
+ data.table.push(row);
122
+
123
+ data.descriptions.push({
124
+ description: refNode.description ? refNode.description.text || "" : "",
125
+ name: refNode.browseName.name!,
126
+ type: dataType
127
+ });
128
+ data.alreadyDumped[key] = 1;
129
+ }
130
+ function dumpReferences(data: Data, _references: UAReference[]) {
131
+ // xx for (const ref of references) {
132
+ // xx dumpReference(ref, "HasSubtype");
133
+ // xx }
134
+ for (const ref of _references) {
135
+ dumpReference(data, ref, "HasTypeDefinition");
136
+ }
137
+ for (const ref of _references) {
138
+ dumpReference(data, ref, "HasEncoding");
139
+ }
140
+ for (const ref of _references) {
141
+ dumpReference(data, ref, "HasComponent");
142
+ }
143
+ for (const ref of _references) {
144
+ dumpReference(data, ref, "HasProperty");
145
+ }
146
+ for (const ref of _references) {
147
+ dumpReference(data, ref, "Organizes");
148
+ }
149
+ for (const ref of _references) {
150
+ console.log(data.node!.addressSpace!.findReferenceType(ref.referenceType)!.toString());
151
+ dumpReference(data, ref, undefined);
152
+ }
153
+ }
154
+
155
+ function shortDescription(d: string) {
156
+ return d.split(/\.|\n/)[0];
157
+ }
41
158
  export function displayNodeElement(node: BaseNode, options?: DisplayNodeOptions): string {
42
159
  const head: string[] = ["ReferenceType", "NodeId", "BrowseName", "ModellingRule", "TypeDefinition", "DataType", "Value"];
43
- const table = new TableHelper(head);
44
160
 
45
- table.push(["BrowseName: ", { colSpan: 6, content: node.browseName.toString() }]);
161
+ function createTable() {
162
+ const table = new TableHelper(head);
163
+ table.push(["BrowseName: ", { colSpan: 6, content: node.browseName.toString() }]);
46
164
 
47
- const superType = (node as UAObjectType).subtypeOfObj;
48
- if (superType) {
49
- table.push(["Base", superType.browseName.toString(), { colSpan: 6, content: node.browseName.toString() }]);
50
- }
165
+ const superType = (node as UAObjectType).subtypeOfObj;
166
+ if (superType) {
167
+ table.push(["Base", superType.browseName.toString(), { colSpan: 6, content: node.browseName.toString() }]);
168
+ }
51
169
 
52
- if (node.description) {
53
- table.push(["Description", node.description.toString(), { colSpan: 6, content: node.browseName.toString() }]);
170
+ if (node.description) {
171
+ table.push(["Description", { colspan: 6, content: shortDescription(node.description.text! || "") }]);
172
+ }
173
+ return table;
54
174
  }
55
175
 
56
- const alreadyDumped: any = {};
176
+ const table = createTable();
57
177
 
58
- const descriptions: any = [];
178
+ const alreadyDumped: Record<string, any> = {};
59
179
 
60
- function dumpReference(ref: UAReference, filter?: string) {
61
- resolveReferenceNode(node.addressSpace, ref);
62
- if (!ref.isForward) {
63
- return;
64
- }
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
- }
83
- }
84
- if (alreadyDumped[refNode.nodeId.toString()]) {
85
- return;
86
- }
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);
113
- }
180
+ const descriptions: Description[] = [];
114
181
 
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;
133
- }
134
182
  const references = node.allReferences();
135
183
 
136
184
  const m = {};
137
185
 
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");
186
+ const data = { table, node, alreadyDumped, descriptions };
187
+ dumpReferences(data, references);
188
+
189
+ function toText(table: TableHelper) {
190
+ if (options && options.format === "markdown") {
191
+ return table.toMarkdownTable();
192
+ } else {
193
+ return table.toString();
156
194
  }
157
195
  }
158
- dumpReferences(references);
196
+
197
+ const str: string[] = [];
198
+ const tables: TableHelper[] = [];
199
+ tables.push(table);
200
+
201
+ if (node.description) {
202
+ str.push(node.description.text! || "");
203
+ str.push("");
204
+ }
205
+ str.push(toText(table));
206
+
207
+ const str2: string[] = [];
159
208
 
160
209
  // add property from base object/variable type
161
210
  if (node.nodeClass === NodeClass.ObjectType || node.nodeClass === NodeClass.VariableType) {
162
211
  const curNode = node;
163
212
 
164
- let subtypeOf = (curNode as UAObjectType).subtypeOfObj;
213
+ let subtypeOf = (curNode as UAObjectType | UAVariableType).subtypeOfObj;
165
214
  while (subtypeOf) {
166
- table.push([subtypeOf.browseName.toString() + ":", "--", "--", "--"]);
215
+ data.table = createTable();
216
+ data.table.push([subtypeOf.browseName.toString() + ":", "--", "--", "--"]);
167
217
  const references2 = subtypeOf.allReferences();
168
- dumpReferences(references2);
218
+ dumpReferences(data, references2);
219
+
220
+ str.push("<details>");
221
+ str.push("<summary>Base type: " + subtypeOf.browseName.toString() + "</summary>");
222
+ str.push("");
223
+ str.push(toText(data.table));
224
+ str.push("");
225
+ str2.push("</details>");
226
+
169
227
  subtypeOf = (subtypeOf as UAObjectType).subtypeOfObj;
170
228
  }
171
229
  }
172
-
173
- if (options && options.format === "markdown") {
174
- return table.toMarkdownTable();
175
- } else {
176
- return table.toString();
177
- }
230
+ return str.join("\n") + str2.join("\n");
178
231
  }
@@ -0,0 +1,164 @@
1
+ /**
2
+ * @module node-opcua-address-space
3
+ */
4
+ // tslint:disable:no-console
5
+ /*
6
+ * class Node {
7
+ * { browseName: "string", nodeId: NodeId}
8
+ * }
9
+ * Transition {
10
+ * browseName: "String"
11
+ * fromState: Node
12
+ * toState: Node
13
+ * }
14
+ * class SateMachineType {
15
+ * initialState: Node
16
+ * states: [ Node,Node, ...]
17
+ * transitions: [Transition]
18
+ * }
19
+ * @param stateMachineType
20
+ */
21
+ import { BaseNode, UAState, UAStateMachineEx, UATransition, UAObject, UATransitionEx } from "node-opcua-address-space";
22
+
23
+
24
+ export function dumpStateMachineToPlantUML(stateMachineType: UAStateMachineEx): string {
25
+
26
+ const lines: string[] = [];
27
+ function w(str: string) {
28
+ lines.push(str);
29
+ }
30
+
31
+ function s(state: BaseNode) {
32
+ return state? state.nodeId.value.toString() : "";
33
+ }
34
+
35
+ function n(state: BaseNode) {
36
+ return state ? state.browseName.name!.toString() : "";
37
+ }
38
+
39
+ //w("@startuml "); // + stateMachineType.browseName.toString() + ".png");
40
+ // initial state if any
41
+
42
+ if (stateMachineType.initialState) {
43
+ w(" [*] --> " + s(stateMachineType.initialState));
44
+ w(" " + s(stateMachineType.initialState) + ":" + n(stateMachineType.initialState));
45
+ } else {
46
+ w("[*] --> [*]");
47
+ }
48
+
49
+ function t(transition: BaseNode) {
50
+ let name = n(transition);
51
+ name = name.replace(":", "");
52
+ name = name.replace("To", "\\nTo\\n");
53
+ name = name.replace("Transition", "\\nTransition");
54
+ return name;
55
+ }
56
+
57
+ stateMachineType.states && stateMachineType.states.forEach((state: UAObject) => w(" " + s(state) + ": " + n(state)));
58
+
59
+ stateMachineType.transitions && stateMachineType.transitions.forEach((transition: UATransitionEx) =>
60
+ w(" " + s(transition.fromStateNode!) + " --> " + s(transition.toStateNode!) + " : " + t(transition))
61
+ );
62
+
63
+ // w("@enduml");
64
+ return lines.join("\n");
65
+
66
+ }
67
+
68
+ /*
69
+ @startuml
70
+
71
+ 2930: Unshelved
72
+
73
+ 2932: TimedShelved
74
+
75
+ 2933: OneShotShelved
76
+
77
+ 2930 --> 2932 : "2935\nUnshelvedToTimedShelved"
78
+
79
+ 2930 --> 2933 : "2936\nUnshelvedToOneShotShelved"
80
+
81
+ 2932 --> 2930 : "2940\nTimedShelvedToUnshelved"
82
+
83
+ 2932 --> 2933 : "2942\nTimedShelvedToOneShotShelved"
84
+
85
+ 2933 --> 2930 : "2943\nOneShotShelvedToUnshelved"
86
+
87
+ 2933 --> 2932 : "2945\nOneShotShelvedToTimedShelved"
88
+
89
+ @enduml
90
+
91
+ */
92
+
93
+ /*
94
+ digraph finite_state_machine {
95
+ rankdir=LR;
96
+ size="8,5"
97
+ node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8;
98
+ node [shape = circle];
99
+ LR_0 -> LR_2 [ label = "SS(B)" ];
100
+ LR_0 -> LR_1 [ label = "SS(S)" ];
101
+ LR_1 -> LR_3 [ label = "S($end)" ];
102
+ LR_2 -> LR_6 [ label = "SS(b)" ];
103
+ LR_2 -> LR_5 [ label = "SS(a)" ];
104
+ LR_2 -> LR_4 [ label = "S(A)" ];
105
+ LR_5 -> LR_7 [ label = "S(b)" ];
106
+ LR_5 -> LR_5 [ label = "S(a)" ];
107
+ LR_6 -> LR_6 [ label = "S(b)" ];
108
+ LR_6 -> LR_5 [ label = "S(a)" ];
109
+ LR_7 -> LR_8 [ label = "S(b)" ];
110
+ LR_7 -> LR_5 [ label = "S(a)" ];
111
+ LR_8 -> LR_6 [ label = "S(b)" ];
112
+ LR_8 -> LR_5 [ label = "S(a)" ];
113
+ }
114
+ */
115
+ export function dumpStateMachineToGraphViz(
116
+ /*StateMachineProxy*/
117
+ stateMachineType: UAStateMachineEx
118
+ ): string {
119
+ const lines: string[] = [];
120
+ function w(str: string) {
121
+ lines.push(str)
122
+ }
123
+
124
+ function s(state: BaseNode) {
125
+ return state.nodeId.value.toString();
126
+ }
127
+
128
+ function n(state: BaseNode) {
129
+ return state.browseName.name!.toString();
130
+ }
131
+
132
+ function s_full(state: BaseNode) {
133
+ return s(state) + ' [ label = "' + n(state) + '" ]';
134
+ }
135
+
136
+ w("digraph finite_state_machine {");
137
+ // initial state if any
138
+
139
+ if (stateMachineType.initialState) {
140
+ w("node [ shape = doublecircle];");
141
+ w(" _" + s_full(stateMachineType.initialState!) + " ;");
142
+ }
143
+ w("node [ shape = circle];");
144
+ stateMachineType.states.forEach((state: UAState) => w(" _" + s_full(state)));
145
+
146
+ stateMachineType.transitions.forEach((transition) =>
147
+ w(
148
+ " _" +
149
+ s(transition.fromStateNode!) +
150
+ " -> _" +
151
+ s(transition.toStateNode!) +
152
+ " [ " +
153
+ // " labeltooltip = \"" + i(transition) + "\" " +
154
+ ', label = "' +
155
+ n(transition) +
156
+ '" ];'
157
+ )
158
+ );
159
+
160
+ w("}");
161
+
162
+ return lines.join("\n");
163
+
164
+ }