@vitormnm/node-red-simple-opcua 1.3.2 → 1.4.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.
- package/README.md +7 -4
- package/client/icons/opcua.svg +132 -0
- package/client/lib/opcua-client-browser.js +46 -7
- package/client/lib/opcua-client-method-service.js +88 -0
- package/client/lib/opcua-client-write-service.js +127 -33
- package/client/opcua-client-config.js +5 -0
- package/client/opcua-client-help.html +61 -0
- package/client/opcua-client-utils.js +68 -2
- package/client/opcua-client.html +14 -1098
- package/client/opcua-client.js +108 -53
- package/client/testClient.json +18 -0
- package/client/view/opcua-client.css +411 -0
- package/client/view/opcua-client.js +1141 -0
- package/icons/opcua.svg +132 -0
- package/icons/opcua2.svg +132 -0
- package/package.json +3 -3
- package/server/icons/opcua.svg +132 -0
- package/server/lib/opcua-address-space-builder.js +24 -2
- package/server/lib/opcua-server-runtime-child.js +117 -26
- package/server/opcua-server-io.html +1 -1
- package/server/opcua-server-io.js +31 -2
- package/server/opcua-server.html +154 -58
- package/server/opcua-server.js +7 -3
- package/object.json +0 -65
package/server/opcua-server.html
CHANGED
|
@@ -238,11 +238,37 @@
|
|
|
238
238
|
color: var(--red-ui-list-item-color-selected, inherit);
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
.opcua-tree-indent {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
241
|
+
.opcua-tree-indent {
|
|
242
|
+
flex: 0 0 auto;
|
|
243
|
+
width: 14px;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.opcua-tree-twisty {
|
|
247
|
+
width: 16px;
|
|
248
|
+
text-align: center;
|
|
249
|
+
color: #777;
|
|
250
|
+
flex: 0 0 16px;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.opcua-tree-icon {
|
|
254
|
+
width: 14px;
|
|
255
|
+
text-align: center;
|
|
256
|
+
color: #777;
|
|
257
|
+
flex: 0 0 14px;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.opcua-tree-label {
|
|
261
|
+
flex: 1 1 auto;
|
|
262
|
+
overflow: hidden;
|
|
263
|
+
text-overflow: ellipsis;
|
|
264
|
+
white-space: nowrap;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.opcua-tree-type {
|
|
268
|
+
color: #777;
|
|
269
|
+
font-size: 11px;
|
|
270
|
+
flex: 0 0 auto;
|
|
271
|
+
}
|
|
246
272
|
|
|
247
273
|
.opcua-tree-context-menu {
|
|
248
274
|
position: fixed;
|
|
@@ -251,7 +277,7 @@
|
|
|
251
277
|
border: 1px solid var(--red-ui-form-input-border-color, #d9d9d9);
|
|
252
278
|
border-radius: 4px;
|
|
253
279
|
background: var(--red-ui-form-input-background, #fff);
|
|
254
|
-
box-shadow: 0 6px 18px rgba(0,0,0,0.18);
|
|
280
|
+
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
|
|
255
281
|
overflow: hidden;
|
|
256
282
|
}
|
|
257
283
|
|
|
@@ -503,7 +529,9 @@
|
|
|
503
529
|
margin-left: 0;
|
|
504
530
|
}
|
|
505
531
|
|
|
506
|
-
.opcua-tree-layout {
|
|
532
|
+
.opcua-tree-layout {
|
|
533
|
+
grid-template-columns: 1fr;
|
|
534
|
+
}
|
|
507
535
|
|
|
508
536
|
.opcua-tree-header {
|
|
509
537
|
align-items: flex-start;
|
|
@@ -644,7 +672,7 @@
|
|
|
644
672
|
};
|
|
645
673
|
}
|
|
646
674
|
|
|
647
|
-
|
|
675
|
+
function normalizeBranch(branch) {
|
|
648
676
|
branch = branch || {};
|
|
649
677
|
return {
|
|
650
678
|
name: branch.name ? String(branch.name) : "",
|
|
@@ -730,6 +758,30 @@
|
|
|
730
758
|
function getNamespaceOptions() {
|
|
731
759
|
return Array.isArray(editorState.nameSpaces) ? editorState.nameSpaces.slice().sort(function (left, right) { return left.id - right.id; }) : [];
|
|
732
760
|
}
|
|
761
|
+
|
|
762
|
+
function getDefinedObjectTypeNames() {
|
|
763
|
+
var names = [];
|
|
764
|
+
(editorState.objectsTypes || []).forEach(function (ot) {
|
|
765
|
+
if (ot && ot.name) names.push(String(ot.name));
|
|
766
|
+
});
|
|
767
|
+
return names;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
function buildObjectTypeSelect(id, currentValue) {
|
|
772
|
+
var names = getDefinedObjectTypeNames();
|
|
773
|
+
var cv = String(currentValue || "");
|
|
774
|
+
var opts = "";
|
|
775
|
+
var noneSelected = (cv === "") ? " selected" : "";
|
|
776
|
+
opts += "<option value=\"\"" + noneSelected + ">\u2014 none \u2014</option>";
|
|
777
|
+
names.forEach(function (n) {
|
|
778
|
+
var esc = n.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
779
|
+
var sel = (n === cv) ? " selected" : "";
|
|
780
|
+
opts += "<option value=\"" + esc + "\"" + sel + ">" + esc + "</option>";
|
|
781
|
+
});
|
|
782
|
+
return "<select id=\"" + id + "\">" + opts + "</select>";
|
|
783
|
+
}
|
|
784
|
+
|
|
733
785
|
function getNamespaceLabel(namespaceId) {
|
|
734
786
|
var match = getNamespaceOptions().find(function (item) { return item.id === normalizeNamespaceId(namespaceId); });
|
|
735
787
|
return match ? String(match.id) + " - " + match.name : String(normalizeNamespaceId(namespaceId));
|
|
@@ -746,8 +798,8 @@
|
|
|
746
798
|
var tokens = pathToTokens(path);
|
|
747
799
|
var current = editorState;
|
|
748
800
|
var parts = [];
|
|
749
|
-
|
|
750
|
-
|
|
801
|
+
// var preservedCollections = { alarms: true, methods: true, objectsTypes: true };
|
|
802
|
+
var preservedCollections = { alarms: true, methods: true };
|
|
751
803
|
|
|
752
804
|
tokens.forEach(function (token) {
|
|
753
805
|
if (/^\d+$/.test(token)) {
|
|
@@ -763,7 +815,7 @@
|
|
|
763
815
|
return parts.join(".");
|
|
764
816
|
}
|
|
765
817
|
|
|
766
|
-
|
|
818
|
+
|
|
767
819
|
function nodeIdSuffixFromValue(nodeId, defaultSuffix) {
|
|
768
820
|
var raw = String(nodeId || "").trim();
|
|
769
821
|
if (!raw) return defaultSuffix;
|
|
@@ -900,43 +952,72 @@
|
|
|
900
952
|
return "fa-tag";
|
|
901
953
|
}
|
|
902
954
|
|
|
903
|
-
|
|
955
|
+
// ── performance helpers ───────────────────────────────────────────
|
|
956
|
+
var _renderTreePending = false;
|
|
957
|
+
|
|
958
|
+
function debounce(fn, delay) {
|
|
959
|
+
var timer;
|
|
960
|
+
return function () { var ctx = this, args = arguments; clearTimeout(timer); timer = setTimeout(function () { fn.apply(ctx, args); }, delay); };
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
function escapeHtml(v) {
|
|
964
|
+
return String(v || "").replace(/[&<>"']/g, function (c) {
|
|
965
|
+
return { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c];
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
function appendNodeToFrag(frag, path, depth, ancestorMatched) {
|
|
904
970
|
var item = getAtPath(editorState, path);
|
|
905
|
-
if (!item) return
|
|
971
|
+
if (!item) return;
|
|
906
972
|
var nodeClass = nodeClassFromPath(path);
|
|
907
973
|
var hasChildren = nodeClass !== "Variable" && nodeClass !== "Alarm" && nodeClass !== "Namespace" && getChildrenByPath(path).length > 0;
|
|
908
|
-
var expanded = isExpanded(path, depth < 1 || treeSearchTerm);
|
|
974
|
+
var expanded = isExpanded(path, depth < 1 || !!treeSearchTerm);
|
|
909
975
|
var subtreeVisible = !!ancestorMatched || nodeMatchesSearch(path);
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
for (var i = 0; i < depth; i +=
|
|
913
|
-
|
|
914
|
-
row
|
|
915
|
-
row.
|
|
916
|
-
row.
|
|
917
|
-
row.
|
|
918
|
-
|
|
976
|
+
|
|
977
|
+
var indents = "";
|
|
978
|
+
for (var i = 0; i < depth; i++) indents += '<span class="opcua-tree-indent"></span>';
|
|
979
|
+
|
|
980
|
+
var row = document.createElement("div");
|
|
981
|
+
row.className = "opcua-tree-row" + (path === selectedPath ? " is-selected" : "");
|
|
982
|
+
row.setAttribute("data-path", path);
|
|
983
|
+
row.innerHTML = indents
|
|
984
|
+
+ '<span class="opcua-tree-twisty">' + (hasChildren ? '<i class="fa ' + (expanded ? "fa-caret-down" : "fa-caret-right") + '"></i>' : "") + "</span>"
|
|
985
|
+
+ '<span class="opcua-tree-icon"><i class="fa ' + iconForNodeClass(nodeClass) + '"></i></span>'
|
|
986
|
+
+ '<span class="opcua-tree-label">' + escapeHtml(item.name || "(unnamed)") + "</span>"
|
|
987
|
+
+ '<span class="opcua-tree-type">' + escapeHtml(nodeClass) + "</span>";
|
|
988
|
+
frag.appendChild(row);
|
|
989
|
+
|
|
919
990
|
if (hasChildren && expanded) {
|
|
920
991
|
getChildrenByPath(path).forEach(function (childPath) {
|
|
921
992
|
if (!treeSearchTerm || subtreeVisible || branchHasSearchMatch(childPath)) {
|
|
922
|
-
|
|
993
|
+
appendNodeToFrag(frag, childPath, depth + 1, subtreeVisible);
|
|
923
994
|
}
|
|
924
995
|
});
|
|
925
996
|
}
|
|
926
|
-
return fragment;
|
|
927
997
|
}
|
|
928
998
|
|
|
929
999
|
function renderTree() {
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
list.
|
|
935
|
-
return;
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
if (!
|
|
939
|
-
|
|
1000
|
+
if (_renderTreePending) return;
|
|
1001
|
+
_renderTreePending = true;
|
|
1002
|
+
setTimeout(function () {
|
|
1003
|
+
_renderTreePending = false;
|
|
1004
|
+
var list = document.getElementById("node-input-object-list");
|
|
1005
|
+
if (!list) return;
|
|
1006
|
+
var frag = document.createDocumentFragment();
|
|
1007
|
+
var roots = getTopLevelPaths();
|
|
1008
|
+
if (!roots.length) {
|
|
1009
|
+
var empty = document.createElement("div");
|
|
1010
|
+
empty.className = "opcua-tree-empty";
|
|
1011
|
+
empty.textContent = "No OPC UA items. Use Add folder, Add object, or Add namespace.";
|
|
1012
|
+
frag.appendChild(empty);
|
|
1013
|
+
} else {
|
|
1014
|
+
roots.forEach(function (path) {
|
|
1015
|
+
if (!treeSearchTerm || branchHasSearchMatch(path)) appendNodeToFrag(frag, path, 0, false);
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
list.innerHTML = "";
|
|
1019
|
+
list.appendChild(frag);
|
|
1020
|
+
}, 0);
|
|
940
1021
|
}
|
|
941
1022
|
|
|
942
1023
|
function renderBreadcrumbs() {
|
|
@@ -972,8 +1053,10 @@
|
|
|
972
1053
|
parentPath: path,
|
|
973
1054
|
kind: kind,
|
|
974
1055
|
name: kind === "variable" ? "newVariable" : kind === "folder" ? "newFolder" : kind === "objecttype" ? "newObjectType" : kind === "alarm" ? "newAlarm" : kind === "method" ? "newMethod" : "newObject",
|
|
1056
|
+
displayName: "",
|
|
975
1057
|
dataType: "Int32",
|
|
976
1058
|
value: "",
|
|
1059
|
+
access: "readwrite",
|
|
977
1060
|
objectsType: "",
|
|
978
1061
|
alarmType: "levelAlarm",
|
|
979
1062
|
variableNodeId: "",
|
|
@@ -1004,24 +1087,27 @@
|
|
|
1004
1087
|
? (parentPath + ".objectsTypes")
|
|
1005
1088
|
: kind === "alarm"
|
|
1006
1089
|
? (parentPath + ".alarms")
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1090
|
+
: kind === "method"
|
|
1091
|
+
? (parentPath + ".methods")
|
|
1092
|
+
: (parentPath + ".objects");
|
|
1010
1093
|
var target = getAtPath(editorState, branchTargetPath);
|
|
1011
1094
|
if (!Array.isArray(target)) return;
|
|
1012
1095
|
if (kind === "variable") {
|
|
1013
1096
|
target.push(normalizeVariable({
|
|
1014
1097
|
name: pendingCreate.name,
|
|
1098
|
+
displayName: pendingCreate.displayName || "",
|
|
1015
1099
|
type: pendingCreate.dataType,
|
|
1016
|
-
value: pendingCreate.value
|
|
1100
|
+
value: pendingCreate.value,
|
|
1101
|
+
access: pendingCreate.access || "readwrite"
|
|
1017
1102
|
}));
|
|
1018
1103
|
} else if (kind === "folder") {
|
|
1019
|
-
target.push(normalizeBranch({ name: pendingCreate.name }));
|
|
1104
|
+
target.push(normalizeBranch({ name: pendingCreate.name, displayName: pendingCreate.displayName || "" }));
|
|
1020
1105
|
} else if (kind === "objecttype") {
|
|
1021
|
-
target.push(normalizeBranch({ name: pendingCreate.name, objectsType: pendingCreate.objectsType || "" }));
|
|
1106
|
+
target.push(normalizeBranch({ name: pendingCreate.name, displayName: pendingCreate.displayName || "", objectsType: pendingCreate.objectsType || "" }));
|
|
1022
1107
|
target[target.length - 1].nodeId = buildGeneratedNodeIdForPath(branchTargetPath + "." + (target.length - 1));
|
|
1023
1108
|
} else if (kind === "alarm") {
|
|
1024
1109
|
target.push(normalizeAlarm({
|
|
1110
|
+
displayName: pendingCreate.displayName || "",
|
|
1025
1111
|
name: pendingCreate.name,
|
|
1026
1112
|
type: pendingCreate.alarmType,
|
|
1027
1113
|
variableNodeId: pendingCreate.variableNodeId,
|
|
@@ -1038,9 +1124,9 @@
|
|
|
1038
1124
|
digitalMessage: pendingCreate.digitalMessage
|
|
1039
1125
|
}));
|
|
1040
1126
|
} else if (kind === "method") {
|
|
1041
|
-
target.push(normalizeMethod({ name: pendingCreate.name }));
|
|
1127
|
+
target.push(normalizeMethod({ name: pendingCreate.name, displayName: pendingCreate.displayName || "" }));
|
|
1042
1128
|
} else {
|
|
1043
|
-
target.push(normalizeBranch({ name: pendingCreate.name }));
|
|
1129
|
+
target.push(normalizeBranch({ name: pendingCreate.name, displayName: pendingCreate.displayName || "" }));
|
|
1044
1130
|
}
|
|
1045
1131
|
expansionState[parentPath] = true;
|
|
1046
1132
|
pendingCreate = null;
|
|
@@ -1060,12 +1146,14 @@
|
|
|
1060
1146
|
panel.append('<div class="form-row"><label>Parent</label><input type="text" id="opcua-create-parent" readonly></div>');
|
|
1061
1147
|
panel.append('<div class="form-row"><label>Type</label><input type="text" id="opcua-create-kind" readonly></div>');
|
|
1062
1148
|
panel.append('<div class="form-row"><label>Name</label><input type="text" id="opcua-create-name"></div>');
|
|
1149
|
+
panel.append('<div class="form-row"><label>displayName</label><input type="text" id="opcua-create-displayname" placeholder="Leave blank to use browseName"></div>');
|
|
1063
1150
|
if (pendingCreate.kind === "variable") {
|
|
1064
1151
|
panel.append('<div class="form-row"><label>dataType</label><select id="opcua-create-type"><option value="Int16">Int16</option><option value="Int32">Int32</option><option value="Float">Float</option><option value="Boolean">Boolean</option><option value="String">String</option></select></div>');
|
|
1065
1152
|
panel.append('<div class="form-row"><label>Value</label><input type="text" id="opcua-create-value"></div>');
|
|
1153
|
+
panel.append('<div class="form-row"><label>Access</label><select id="opcua-create-access"><option value="readwrite">readwrite</option><option value="readonly">readonly</option></select></div>');
|
|
1066
1154
|
}
|
|
1067
1155
|
if (pendingCreate.kind === "objecttype") {
|
|
1068
|
-
panel.append('<div class="form-row"><label>objectsType</label
|
|
1156
|
+
panel.append('<div class="form-row"><label>objectsType</label>' + buildObjectTypeSelect("opcua-create-objectstype", pendingCreate.objectsType || "") + '</div>');
|
|
1069
1157
|
}
|
|
1070
1158
|
if (pendingCreate.kind === "alarm") {
|
|
1071
1159
|
panel.append('<div class="form-row"><label>alarmType</label><select id="opcua-create-alarm-type"><option value="levelAlarm">levelAlarm</option><option value="digitalAlarm">digitalAlarm</option></select></div>');
|
|
@@ -1089,9 +1177,11 @@
|
|
|
1089
1177
|
$("#opcua-create-parent").val(pendingCreate.parentPath);
|
|
1090
1178
|
$("#opcua-create-kind").val(pendingCreate.kind);
|
|
1091
1179
|
$("#opcua-create-name").val(pendingCreate.name);
|
|
1180
|
+
$("#opcua-create-displayname").val(pendingCreate.displayName || "");
|
|
1092
1181
|
$("#opcua-create-type").val(pendingCreate.dataType);
|
|
1093
1182
|
$("#opcua-create-value").val(pendingCreate.value);
|
|
1094
1183
|
$("#opcua-create-objectstype").val(pendingCreate.objectsType);
|
|
1184
|
+
$("#opcua-create-access").val(pendingCreate.access || "readwrite");
|
|
1095
1185
|
$("#opcua-create-alarm-type").val(pendingCreate.alarmType);
|
|
1096
1186
|
$("#opcua-create-variable-nodeid").val(pendingCreate.variableNodeId);
|
|
1097
1187
|
$("#opcua-create-severity").val(pendingCreate.severity);
|
|
@@ -1130,15 +1220,16 @@
|
|
|
1130
1220
|
panel.append('<div class="form-row"><label>namespace</label><select id="opcua-detail-namespace"></select></div>');
|
|
1131
1221
|
panel.append('<div class="form-row"><label>nodeId</label><div class="opcua-nodeid-field"><span class="opcua-nodeid-prefix">' + getNodeIdPrefix(namespaceId) + '</span><input type="text" id="opcua-detail-nodeid"' + (nodeIdLocked ? ' readonly title="Generated automatically for object type models."' : '') + '><a href="#" id="opcua-detail-copy-nodeid" class="editor-button editor-button-small"><i class="fa fa-copy"></i> Copy</a></div></div>');
|
|
1132
1222
|
panel.append('<div class="form-row"><label>Description</label><input type="text" id="opcua-detail-description"></div>');
|
|
1223
|
+
panel.append('<div class="form-row"><label>displayName</label><input type="text" id="opcua-detail-displayname" placeholder="Leave blank to use browseName"></div>');
|
|
1133
1224
|
if (nodeClass === "ObjectType") {
|
|
1134
|
-
panel.append('<div class="form-row"><label>objectsType</label
|
|
1225
|
+
panel.append('<div class="form-row"><label>objectsType</label>' + buildObjectTypeSelect("opcua-detail-objectstype", item.objectsType || "") + '</div>');
|
|
1135
1226
|
}
|
|
1136
1227
|
if (nodeClass === "Variable") {
|
|
1137
|
-
panel.append('<div class="form-row"><label>dataType</label><select id="opcua-detail-type"><option value="Int16">Int16</option><option value="Int32">Int32</option><option value="Float">Float</option><option value="Boolean">Boolean</option><option value="String">String</option></select></div>');
|
|
1228
|
+
panel.append('<div class="form-row"><label>dataType</label><select id="opcua-detail-type"><option value="Int16">Int16</option><option value="Int32">Int32</option><option value="Float">Float</option><option value="Boolean">Boolean</option><option value="String">String</option><option value="ByteString">ByteString</option></select></div>');
|
|
1138
1229
|
panel.append('<div class="form-row"><label>Value</label><input type="text" id="opcua-detail-value"></div>');
|
|
1230
|
+
panel.append('<div class="form-row"><label>Access</label><select id="opcua-detail-access"><option value="readwrite">readwrite</option><option value="readonly">readonly</option></select></div>');
|
|
1139
1231
|
}
|
|
1140
1232
|
if (nodeClass === "Method") {
|
|
1141
|
-
panel.append('<div class="form-row"><label>displayName</label><input type="text" id="opcua-detail-displayname"></div>');
|
|
1142
1233
|
panel.append('<hr style="margin:8px 0; border-color:#e3e3e3;">');
|
|
1143
1234
|
panel.append('<div style="font-size:11px;font-weight:700;text-transform:uppercase;color:#666;margin-bottom:4px;">Inputs</div>');
|
|
1144
1235
|
var inputsDiv = $('<div id="opcua-detail-inputs"></div>').appendTo(panel);
|
|
@@ -1176,7 +1267,7 @@
|
|
|
1176
1267
|
});
|
|
1177
1268
|
panel.append('<div class="form-row"><label></label><a href="#" class="editor-button editor-button-small" id="opcua-method-add-output"><i class="fa fa-plus"></i> Add output</a></div>');
|
|
1178
1269
|
}
|
|
1179
|
-
|
|
1270
|
+
if (nodeClass === "Alarm") {
|
|
1180
1271
|
panel.append('<div class="form-row"><label>alarmType</label><select id="opcua-detail-alarm-type"><option value="levelAlarm">levelAlarm</option><option value="digitalAlarm">digitalAlarm</option></select></div>');
|
|
1181
1272
|
panel.append('<div class="form-row"><label>variablePath</label><input type="text" id="opcua-detail-variable-nodeid"></div>');
|
|
1182
1273
|
panel.append('<div class="form-row"><label>severity</label><input type="number" id="opcua-detail-severity"></div>');
|
|
@@ -1203,9 +1294,9 @@
|
|
|
1203
1294
|
$("#opcua-detail-namespace").append($("<option></option>").val(option.id).text(getNamespaceLabel(option.id)));
|
|
1204
1295
|
});
|
|
1205
1296
|
$("#opcua-detail-namespace").val(String(namespaceId));
|
|
1206
|
-
|
|
1207
|
-
if (nodeClass === "ObjectType") $("#opcua-detail-objectstype").val(item.objectsType || "");
|
|
1208
|
-
if (nodeClass === "Variable") { $("#opcua-detail-type").val(item.type || "Int32"); $("#opcua-detail-value").val(item.value !== undefined ? item.value : ""); }
|
|
1297
|
+
$("#opcua-detail-displayname").val(item.displayName || "");
|
|
1298
|
+
if (nodeClass === "ObjectType") { $("#opcua-detail-objectstype").val(item.objectsType || ""); }
|
|
1299
|
+
if (nodeClass === "Variable") { $("#opcua-detail-type").val(item.type || "Int32"); $("#opcua-detail-value").val(item.value !== undefined ? item.value : ""); $("#opcua-detail-access").val(item.access || "readwrite"); }
|
|
1209
1300
|
if (nodeClass === "Alarm") {
|
|
1210
1301
|
$("#opcua-detail-alarm-type").val(item.type || "levelAlarm");
|
|
1211
1302
|
$("#opcua-detail-variable-nodeid").val(item.variableNodeId || "");
|
|
@@ -1360,7 +1451,7 @@
|
|
|
1360
1451
|
|
|
1361
1452
|
$(document).on("input", "#opcua-detail-displayname", function () { updateNode(selectedPath, { displayName: $(this).val() }); });
|
|
1362
1453
|
|
|
1363
|
-
|
|
1454
|
+
$(document).on("input", "#opcua-detail-name", function () { updateNode(selectedPath, { name: $(this).val() }); });
|
|
1364
1455
|
$(document).on("change", "#opcua-detail-namespace", function () {
|
|
1365
1456
|
var nextNamespaceId = normalizeNamespaceId($(this).val());
|
|
1366
1457
|
var item = getAtPath(editorState, selectedPath);
|
|
@@ -1398,8 +1489,9 @@
|
|
|
1398
1489
|
}
|
|
1399
1490
|
});
|
|
1400
1491
|
$(document).on("input", "#opcua-detail-description", function () { updateNode(selectedPath, { description: $(this).val() }); });
|
|
1401
|
-
$(document).on("
|
|
1492
|
+
$(document).on("change", "#opcua-detail-objectstype", function () { updateNode(selectedPath, { objectsType: $(this).val() }); });
|
|
1402
1493
|
$(document).on("change", "#opcua-detail-type", function () { updateNode(selectedPath, { type: $(this).val() }); });
|
|
1494
|
+
$(document).on("change", "#opcua-detail-access", function () { updateNode(selectedPath, { access: $(this).val() }); });
|
|
1403
1495
|
$(document).on("input", "#opcua-detail-value", function () { updateNode(selectedPath, { value: $(this).val() }); });
|
|
1404
1496
|
$(document).on("change", "#opcua-detail-alarm-type", function () {
|
|
1405
1497
|
updateNode(selectedPath, { type: $(this).val() });
|
|
@@ -1418,9 +1510,11 @@
|
|
|
1418
1510
|
$(document).on("input", "#opcua-detail-normalstatevalue", function () { updateNode(selectedPath, { normalStateValue: Number($(this).val() || 0) }); });
|
|
1419
1511
|
$(document).on("input", "#opcua-detail-digitalmessage", function () { updateNode(selectedPath, { digitalMessage: $(this).val() }); });
|
|
1420
1512
|
$(document).on("input", "#opcua-create-name", function () { if (pendingCreate) pendingCreate.name = $(this).val(); });
|
|
1513
|
+
$(document).on("input", "#opcua-create-displayname", function () { if (pendingCreate) pendingCreate.displayName = $(this).val(); });
|
|
1421
1514
|
$(document).on("change", "#opcua-create-type", function () { if (pendingCreate) pendingCreate.dataType = $(this).val(); });
|
|
1422
1515
|
$(document).on("input", "#opcua-create-value", function () { if (pendingCreate) pendingCreate.value = $(this).val(); });
|
|
1423
|
-
$(document).on("
|
|
1516
|
+
$(document).on("change", "#opcua-create-objectstype", function () { if (pendingCreate) pendingCreate.objectsType = $(this).val(); });
|
|
1517
|
+
$(document).on("change", "#opcua-create-access", function () { if (pendingCreate) pendingCreate.access = $(this).val(); });
|
|
1424
1518
|
$(document).on("change", "#opcua-create-alarm-type", function () {
|
|
1425
1519
|
if (pendingCreate) {
|
|
1426
1520
|
pendingCreate.alarmType = $(this).val();
|
|
@@ -1461,7 +1555,9 @@
|
|
|
1461
1555
|
}
|
|
1462
1556
|
}
|
|
1463
1557
|
},
|
|
1464
|
-
inputs: 1,
|
|
1558
|
+
inputs: 1,
|
|
1559
|
+
outputs: 0,
|
|
1560
|
+
icon: "opcua.svg",
|
|
1465
1561
|
label: function () { return this.name || this.serverName || "opc-ua-server"; },
|
|
1466
1562
|
oneditprepare: function () {
|
|
1467
1563
|
var node = this;
|
|
@@ -1487,10 +1583,10 @@
|
|
|
1487
1583
|
$("#node-input-close-tree-modal").off("click").on("click", function (event) { event.preventDefault(); closeTreeModal(); });
|
|
1488
1584
|
$("#node-input-tree-modal").off("click").on("click", function (event) { if (event.target === this) closeTreeModal(); });
|
|
1489
1585
|
|
|
1490
|
-
$("#node-input-tree-search").off("input").on("input", function () {
|
|
1586
|
+
$("#node-input-tree-search").off("input").on("input", debounce(function () {
|
|
1491
1587
|
treeSearchValue = $(this).val(); treeSearchTerm = normalizeSearchTerm(treeSearchValue);
|
|
1492
1588
|
$("#node-input-tree-search-clear").toggle(!!treeSearchTerm); renderTree();
|
|
1493
|
-
});
|
|
1589
|
+
}, 200));
|
|
1494
1590
|
$("#node-input-tree-search-clear").off("click").on("click", function (event) {
|
|
1495
1591
|
event.preventDefault(); treeSearchValue = ""; treeSearchTerm = "";
|
|
1496
1592
|
$("#node-input-tree-search").val(""); $(this).hide(); renderTree();
|
|
@@ -1545,4 +1641,4 @@
|
|
|
1545
1641
|
<p>Supported variable types: <code>Int32</code>, <code>Float</code>, <code>Boolean</code>, <code>String</code>.</p>
|
|
1546
1642
|
<p>Supported access modes: <code>readonly</code> and <code>readwrite</code>.</p>
|
|
1547
1643
|
<p>Authentication can be configured in the editor with a local username list and bcrypt password hashes, and anonymous login can be disabled.</p>
|
|
1548
|
-
</script>
|
|
1644
|
+
</script>
|
package/server/opcua-server.js
CHANGED
|
@@ -9,6 +9,8 @@ module.exports = function (RED) {
|
|
|
9
9
|
const path = require("path");
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
|
|
@@ -16,9 +18,11 @@ module.exports = function (RED) {
|
|
|
16
18
|
RED.nodes.createNode(this, config);
|
|
17
19
|
const node = this;
|
|
18
20
|
const parser = new OpcUaServerConfigParser(node);
|
|
19
|
-
|
|
21
|
+
|
|
20
22
|
const settings = parser.parseNodeConfig(config, this.credentials || {});
|
|
21
23
|
|
|
24
|
+
|
|
25
|
+
|
|
22
26
|
node.name = settings.name;
|
|
23
27
|
node.serverName = settings.serverName;
|
|
24
28
|
node.server = null;
|
|
@@ -58,7 +62,7 @@ module.exports = function (RED) {
|
|
|
58
62
|
});
|
|
59
63
|
|
|
60
64
|
|
|
61
|
-
|
|
65
|
+
|
|
62
66
|
child.send({
|
|
63
67
|
type: "createServer",
|
|
64
68
|
config: config,
|
|
@@ -70,7 +74,7 @@ module.exports = function (RED) {
|
|
|
70
74
|
child.on("message", (msg) => {
|
|
71
75
|
if (msg.nodeId == node.id) {
|
|
72
76
|
if (msg.type === "status") {
|
|
73
|
-
|
|
77
|
+
|
|
74
78
|
node.status(msg.data); // aqui sim usa o node
|
|
75
79
|
}
|
|
76
80
|
|
package/object.json
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"objects": [],
|
|
3
|
-
"folders": [
|
|
4
|
-
{
|
|
5
|
-
"name": "site",
|
|
6
|
-
"folders": [
|
|
7
|
-
{
|
|
8
|
-
"name": "line1",
|
|
9
|
-
"folders": [],
|
|
10
|
-
"objects": [
|
|
11
|
-
{
|
|
12
|
-
"name": "motor",
|
|
13
|
-
"folders": [],
|
|
14
|
-
"objects": [],
|
|
15
|
-
"variables": [
|
|
16
|
-
{
|
|
17
|
-
"name": "speed",
|
|
18
|
-
"type": "Float",
|
|
19
|
-
"value": "",
|
|
20
|
-
"access": "readonly",
|
|
21
|
-
"description": "",
|
|
22
|
-
"displayName": ""
|
|
23
|
-
}
|
|
24
|
-
],
|
|
25
|
-
"method": [
|
|
26
|
-
{
|
|
27
|
-
"name": "cmd_on",
|
|
28
|
-
"description": "",
|
|
29
|
-
"displayName": "",
|
|
30
|
-
"inputs": [
|
|
31
|
-
{
|
|
32
|
-
"name": "sp_speed",
|
|
33
|
-
"type": "Float",
|
|
34
|
-
"displayName": ""
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"name": "cmd_on",
|
|
38
|
-
"type": "Boolean",
|
|
39
|
-
"displayName": ""
|
|
40
|
-
}
|
|
41
|
-
],
|
|
42
|
-
"outputs": [
|
|
43
|
-
{
|
|
44
|
-
"name": "sts_spped",
|
|
45
|
-
"type": "Float",
|
|
46
|
-
"displayName": ""
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"name": "sts_motor",
|
|
50
|
-
"type": "Boolean",
|
|
51
|
-
"displayName": ""
|
|
52
|
-
}
|
|
53
|
-
]
|
|
54
|
-
}
|
|
55
|
-
]
|
|
56
|
-
}
|
|
57
|
-
],
|
|
58
|
-
"variables": []
|
|
59
|
-
}
|
|
60
|
-
],
|
|
61
|
-
"objects": [],
|
|
62
|
-
"variables": []
|
|
63
|
-
}
|
|
64
|
-
]
|
|
65
|
-
}
|