@frangoteam/fuxa-min 1.2.11 → 1.3.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.
- package/api/auth/index.js +141 -3
- package/api/index.js +18 -2
- package/api/jwt-helper.js +3 -1
- package/api/resources/index.js +19 -2
- package/dist/3rdpartylicenses.txt +139 -7
- package/dist/assets/i18n/de.json +10 -0
- package/dist/assets/i18n/en.json +14 -3
- package/dist/assets/i18n/es.json +12 -0
- package/dist/assets/i18n/fr.json +10 -0
- package/dist/assets/i18n/ja.json +15 -6
- package/dist/assets/i18n/ko.json +12 -0
- package/dist/assets/i18n/pt.json +9 -2
- package/dist/assets/i18n/ru.json +11 -0
- package/dist/assets/i18n/sv.json +10 -1
- package/dist/assets/i18n/tr.json +8 -1
- package/dist/assets/i18n/ua.json +9 -2
- package/dist/assets/i18n/zh-cn.json +10 -0
- package/dist/assets/i18n/zh-tw.json +11 -1
- package/dist/index.html +2 -2
- package/dist/main.bafae830903d548e.js +329 -0
- package/dist/polyfills.d7de05f9af2fb559.js +1 -0
- package/dist/{runtime.8ef63094e52a66ba.js → runtime.9136a61a9b98f987.js} +1 -1
- package/dist/{scripts.40b60f02658462e4.js → scripts.d9e6ee984bf6f3b7.js} +1 -1
- package/dist/styles.545e37beb3e671ba.css +1 -0
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-daq.html +56 -5
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-daq.js +8 -2
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag-change.html +56 -5
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag-change.js +12 -12
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag-daq-settings.html +56 -5
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag-daq-settings.js +14 -10
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag.html +56 -5
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag.js +8 -2
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-set-tag-daq-settings.html +56 -5
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-set-tag-daq-settings.js +24 -20
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-set-tag.html +56 -5
- package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-set-tag.js +8 -2
- package/main.js +35 -17
- package/package.json +10 -5
- package/runtime/devices/adsclient/index.js +1 -1
- package/runtime/devices/ethernetip/index.js +1 -1
- package/runtime/devices/gpio/index.js +1 -1
- package/runtime/devices/odbc/index.js +5 -5
- package/runtime/devices/template/index.js +14 -14
- package/runtime/storage/daqstorage.js +28 -2
- package/runtime/storage/questdb/index.js +224 -0
- package/runtime/utils.js +5 -0
- package/settings.default.js +5 -2
- package/dist/main.92522279642ef880.js +0 -329
- package/dist/polyfills.c8e7db9850a3ad8b.js +0 -1
- package/dist/styles.03cc550382689976.css +0 -1
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
color: '#a6bbcf',
|
|
5
5
|
defaults: {
|
|
6
6
|
name: {value:""},
|
|
7
|
-
tag: {value:"",
|
|
7
|
+
tag: {value:""}, // Keep: tag name for display and backward compatibility
|
|
8
|
+
tagId: {value:""}, // New: unique identifier (optional, for backward compatibility)
|
|
8
9
|
from: {value:""},
|
|
9
10
|
to: {value:""}
|
|
10
11
|
},
|
|
@@ -12,17 +13,65 @@
|
|
|
12
13
|
outputs:1,
|
|
13
14
|
icon: "white-globe.png",
|
|
14
15
|
label: function() {
|
|
15
|
-
|
|
16
|
+
if (this.name) {
|
|
17
|
+
return this.name;
|
|
18
|
+
}
|
|
19
|
+
// Display tag name or tagId
|
|
20
|
+
return this.tag || this.tagId || "get daq";
|
|
16
21
|
},
|
|
17
22
|
oneditprepare: function() {
|
|
23
|
+
var node = this;
|
|
24
|
+
var tagMap = {}; // Use tag.id as key to avoid tag.name duplication issues
|
|
25
|
+
|
|
18
26
|
$.getJSON('/nodered/fuxa/devices', function(data) {
|
|
19
27
|
var datalist = $('#fuxa-tags-daq');
|
|
20
28
|
datalist.empty();
|
|
29
|
+
|
|
21
30
|
data.forEach(function(device) {
|
|
22
31
|
device.tags.forEach(function(tag) {
|
|
23
|
-
|
|
32
|
+
var fullName = device.name + ' - ' + tag.name;
|
|
33
|
+
// datalist option value format: tag.name(tag.id)
|
|
34
|
+
var optionValue = tag.name + '(' + tag.id + ')';
|
|
35
|
+
datalist.append('<option value="' + optionValue + '">' + fullName + '</option>');
|
|
36
|
+
tagMap[tag.id] = {
|
|
37
|
+
name: tag.name,
|
|
38
|
+
deviceName: device.name,
|
|
39
|
+
fullName: fullName
|
|
40
|
+
};
|
|
24
41
|
});
|
|
25
42
|
});
|
|
43
|
+
|
|
44
|
+
// Listen for tagSelected input changes
|
|
45
|
+
$('#node-input-tagSelected').on('change', function() {
|
|
46
|
+
var selectedValue = $(this).val();
|
|
47
|
+
// Parse format: tag.name(tag.id)
|
|
48
|
+
var match = selectedValue.match(/^(.+)\(([^)]+)\)$/);
|
|
49
|
+
if (match) {
|
|
50
|
+
var tagName = match[1];
|
|
51
|
+
var tagId = match[2];
|
|
52
|
+
|
|
53
|
+
// Set the actual stored fields
|
|
54
|
+
$('#node-input-tag').val(tagName);
|
|
55
|
+
$('#node-input-tagId').val(tagId);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Initialize display (when editing existing node)
|
|
60
|
+
if (node.tagId && tagMap[node.tagId]) {
|
|
61
|
+
// Has tagId, construct tagSelected value
|
|
62
|
+
var tagName = node.tag || tagMap[node.tagId].name;
|
|
63
|
+
$('#node-input-tagSelected').val(tagName + '(' + node.tagId + ')');
|
|
64
|
+
} else if (node.tag && !node.tagId) {
|
|
65
|
+
// Old node: only has tag (tag.name), need to find corresponding tagId
|
|
66
|
+
// Note: if there are duplicate names, only the first match will be found
|
|
67
|
+
for (var tagId in tagMap) {
|
|
68
|
+
if (tagMap[tagId].name === node.tag) {
|
|
69
|
+
$('#node-input-tagSelected').val(node.tag + '(' + tagId + ')');
|
|
70
|
+
$('#node-input-tagId').val(tagId);
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
26
75
|
});
|
|
27
76
|
|
|
28
77
|
// Convert timestamp format for datetime-local inputs
|
|
@@ -64,10 +113,12 @@
|
|
|
64
113
|
<input type="text" id="node-input-name" placeholder="Name">
|
|
65
114
|
</div>
|
|
66
115
|
<div class="form-row">
|
|
67
|
-
<label for="node-input-
|
|
68
|
-
<input type="text" id="node-input-
|
|
116
|
+
<label for="node-input-tagSelected"><i class="fa fa-tag"></i> Tag</label>
|
|
117
|
+
<input type="text" id="node-input-tagSelected" list="fuxa-tags-daq" placeholder="Select Tag">
|
|
69
118
|
<datalist id="fuxa-tags-daq"></datalist>
|
|
70
119
|
</div>
|
|
120
|
+
<input type="hidden" id="node-input-tag">
|
|
121
|
+
<input type="hidden" id="node-input-tagId">
|
|
71
122
|
<div class="form-row">
|
|
72
123
|
<label for="node-input-from"><i class="fa fa-clock-o"></i> From (timestamp)</label>
|
|
73
124
|
<input type="datetime-local" id="node-input-from" placeholder="From timestamp (optional)">
|
|
@@ -6,7 +6,13 @@ module.exports = function(RED) {
|
|
|
6
6
|
|
|
7
7
|
this.on('input', async function(msg) {
|
|
8
8
|
try {
|
|
9
|
-
|
|
9
|
+
// Prefer config.tagId, fallback to config.tag for backward compatibility
|
|
10
|
+
var tagId = config.tagId;
|
|
11
|
+
if (!tagId && config.tag) {
|
|
12
|
+
// Backward compatibility: old nodes use tag.name, need to convert to tagId
|
|
13
|
+
tagId = fuxa.getTagId(config.tag, null);
|
|
14
|
+
}
|
|
15
|
+
|
|
10
16
|
if (tagId) {
|
|
11
17
|
var fromts = config.from || msg.from || Date.now() - 3600000; // default 1 hour ago
|
|
12
18
|
var tots = config.to || msg.to || Date.now();
|
|
@@ -14,7 +20,7 @@ module.exports = function(RED) {
|
|
|
14
20
|
msg.payload = data;
|
|
15
21
|
node.send(msg);
|
|
16
22
|
} else {
|
|
17
|
-
node.error('Tag not found: ' + config.tag, msg);
|
|
23
|
+
node.error('Tag not found: ' + (config.tag || config.tagId), msg);
|
|
18
24
|
}
|
|
19
25
|
} catch (err) {
|
|
20
26
|
node.error(err, msg);
|
|
@@ -4,23 +4,72 @@
|
|
|
4
4
|
color: '#a6bbcf',
|
|
5
5
|
defaults: {
|
|
6
6
|
name: {value:""},
|
|
7
|
-
tag: {value:"",
|
|
7
|
+
tag: {value:""}, // Keep: tag name for display and backward compatibility
|
|
8
|
+
tagId: {value:""} // New: unique identifier (optional, for backward compatibility)
|
|
8
9
|
},
|
|
9
10
|
inputs:0,
|
|
10
11
|
outputs:1,
|
|
11
12
|
icon: "white-globe.png",
|
|
12
13
|
label: function() {
|
|
13
|
-
|
|
14
|
+
if (this.name) {
|
|
15
|
+
return this.name;
|
|
16
|
+
}
|
|
17
|
+
// Display tag name or tagId
|
|
18
|
+
return this.tag || this.tagId || "get tag change";
|
|
14
19
|
},
|
|
15
20
|
oneditprepare: function() {
|
|
21
|
+
var node = this;
|
|
22
|
+
var tagMap = {}; // Use tag.id as key to avoid tag.name duplication issues
|
|
23
|
+
|
|
16
24
|
$.getJSON('/nodered/fuxa/devices', function(data) {
|
|
17
25
|
var datalist = $('#fuxa-change-tags');
|
|
18
26
|
datalist.empty();
|
|
27
|
+
|
|
19
28
|
data.forEach(function(device) {
|
|
20
29
|
device.tags.forEach(function(tag) {
|
|
21
|
-
|
|
30
|
+
var fullName = device.name + ' - ' + tag.name;
|
|
31
|
+
// datalist option value format: tag.name(tag.id)
|
|
32
|
+
var optionValue = tag.name + '(' + tag.id + ')';
|
|
33
|
+
datalist.append('<option value="' + optionValue + '">' + fullName + '</option>');
|
|
34
|
+
tagMap[tag.id] = {
|
|
35
|
+
name: tag.name,
|
|
36
|
+
deviceName: device.name,
|
|
37
|
+
fullName: fullName
|
|
38
|
+
};
|
|
22
39
|
});
|
|
23
40
|
});
|
|
41
|
+
|
|
42
|
+
// Listen for tagSelected input changes
|
|
43
|
+
$('#node-input-tagSelected').on('change', function() {
|
|
44
|
+
var selectedValue = $(this).val();
|
|
45
|
+
// Parse format: tag.name(tag.id)
|
|
46
|
+
var match = selectedValue.match(/^(.+)\(([^)]+)\)$/);
|
|
47
|
+
if (match) {
|
|
48
|
+
var tagName = match[1];
|
|
49
|
+
var tagId = match[2];
|
|
50
|
+
|
|
51
|
+
// Set the actual stored fields
|
|
52
|
+
$('#node-input-tag').val(tagName);
|
|
53
|
+
$('#node-input-tagId').val(tagId);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Initialize display (when editing existing node)
|
|
58
|
+
if (node.tagId && tagMap[node.tagId]) {
|
|
59
|
+
// Has tagId, construct tagSelected value
|
|
60
|
+
var tagName = node.tag || tagMap[node.tagId].name;
|
|
61
|
+
$('#node-input-tagSelected').val(tagName + '(' + node.tagId + ')');
|
|
62
|
+
} else if (node.tag && !node.tagId) {
|
|
63
|
+
// Old node: only has tag (tag.name), need to find corresponding tagId
|
|
64
|
+
// Note: if there are duplicate names, only the first match will be found
|
|
65
|
+
for (var tagId in tagMap) {
|
|
66
|
+
if (tagMap[tagId].name === node.tag) {
|
|
67
|
+
$('#node-input-tagSelected').val(node.tag + '(' + tagId + ')');
|
|
68
|
+
$('#node-input-tagId').val(tagId);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
24
73
|
});
|
|
25
74
|
}
|
|
26
75
|
});
|
|
@@ -32,10 +81,12 @@
|
|
|
32
81
|
<input type="text" id="node-input-name" placeholder="Name">
|
|
33
82
|
</div>
|
|
34
83
|
<div class="form-row">
|
|
35
|
-
<label for="node-input-
|
|
36
|
-
<input type="text" id="node-input-
|
|
84
|
+
<label for="node-input-tagSelected"><i class="fa fa-tag"></i> Tag</label>
|
|
85
|
+
<input type="text" id="node-input-tagSelected" list="fuxa-change-tags" placeholder="Select Tag">
|
|
37
86
|
<datalist id="fuxa-change-tags"></datalist>
|
|
38
87
|
</div>
|
|
88
|
+
<input type="hidden" id="node-input-tag">
|
|
89
|
+
<input type="hidden" id="node-input-tagId">
|
|
39
90
|
</script>
|
|
40
91
|
|
|
41
92
|
<script type="text/x-red" data-help-name="get-tag-change">
|
|
@@ -7,26 +7,26 @@ module.exports = function(RED) {
|
|
|
7
7
|
// Store previous values to detect actual changes
|
|
8
8
|
var previousValues = {};
|
|
9
9
|
|
|
10
|
+
// Prefer config.tagId, fallback to config.tag for backward compatibility
|
|
11
|
+
var configuredTagId = config.tagId;
|
|
12
|
+
if (!configuredTagId && config.tag) {
|
|
13
|
+
// Backward compatibility: old nodes use tag.name, need to convert to tagId
|
|
14
|
+
configuredTagId = fuxa.getTagId(config.tag, null);
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
// Initialize previous value for the configured tag
|
|
11
|
-
if (
|
|
12
|
-
var
|
|
13
|
-
if (
|
|
14
|
-
|
|
15
|
-
var initialValue = fuxa.getTag(tagId);
|
|
16
|
-
if (initialValue !== undefined) {
|
|
17
|
-
previousValues[tagId] = initialValue;
|
|
18
|
-
}
|
|
18
|
+
if (configuredTagId) {
|
|
19
|
+
var initialValue = fuxa.getTag(configuredTagId);
|
|
20
|
+
if (initialValue !== undefined) {
|
|
21
|
+
previousValues[configuredTagId] = initialValue;
|
|
19
22
|
}
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
// Event listener for device value changes (raw events from devices)
|
|
23
26
|
var deviceEventListener = function(deviceEvent) {
|
|
24
27
|
try {
|
|
25
28
|
// deviceEvent format: { id: deviceId, values: { tagId: tagObject, ... } }
|
|
26
29
|
if (deviceEvent && deviceEvent.values) {
|
|
27
|
-
// Check if any of the changed values match our configured tag
|
|
28
|
-
var configuredTagId = fuxa.getTagId(config.tag, null);
|
|
29
|
-
|
|
30
30
|
if (configuredTagId && deviceEvent.values[configuredTagId]) {
|
|
31
31
|
var tagData = deviceEvent.values[configuredTagId];
|
|
32
32
|
|
|
@@ -4,23 +4,72 @@
|
|
|
4
4
|
color: '#a6bbcf',
|
|
5
5
|
defaults: {
|
|
6
6
|
name: {value:""},
|
|
7
|
-
tag: {value:"",
|
|
7
|
+
tag: {value:""}, // Keep: tag name for display and backward compatibility
|
|
8
|
+
tagId: {value:""} // New: unique identifier (optional, for backward compatibility)
|
|
8
9
|
},
|
|
9
10
|
inputs:1,
|
|
10
11
|
outputs:1,
|
|
11
12
|
icon: "white-globe.png",
|
|
12
13
|
label: function() {
|
|
13
|
-
|
|
14
|
+
if (this.name) {
|
|
15
|
+
return this.name;
|
|
16
|
+
}
|
|
17
|
+
// Display tag name or tagId
|
|
18
|
+
return this.tag || this.tagId || "get tag daq settings";
|
|
14
19
|
},
|
|
15
20
|
oneditprepare: function() {
|
|
21
|
+
var node = this;
|
|
22
|
+
var tagMap = {}; // Use tag.id as key to avoid tag.name duplication issues
|
|
23
|
+
|
|
16
24
|
$.getJSON('/nodered/fuxa/devices', function(data) {
|
|
17
25
|
var datalist = $('#fuxa-tags-daq-settings');
|
|
18
26
|
datalist.empty();
|
|
27
|
+
|
|
19
28
|
data.forEach(function(device) {
|
|
20
29
|
device.tags.forEach(function(tag) {
|
|
21
|
-
|
|
30
|
+
var fullName = device.name + ' - ' + tag.name;
|
|
31
|
+
// datalist option value format: tag.name(tag.id)
|
|
32
|
+
var optionValue = tag.name + '(' + tag.id + ')';
|
|
33
|
+
datalist.append('<option value="' + optionValue + '">' + fullName + '</option>');
|
|
34
|
+
tagMap[tag.id] = {
|
|
35
|
+
name: tag.name,
|
|
36
|
+
deviceName: device.name,
|
|
37
|
+
fullName: fullName
|
|
38
|
+
};
|
|
22
39
|
});
|
|
23
40
|
});
|
|
41
|
+
|
|
42
|
+
// Listen for tagSelected input changes
|
|
43
|
+
$('#node-input-tagSelected').on('change', function() {
|
|
44
|
+
var selectedValue = $(this).val();
|
|
45
|
+
// Parse format: tag.name(tag.id)
|
|
46
|
+
var match = selectedValue.match(/^(.+)\(([^)]+)\)$/);
|
|
47
|
+
if (match) {
|
|
48
|
+
var tagName = match[1];
|
|
49
|
+
var tagId = match[2];
|
|
50
|
+
|
|
51
|
+
// Set the actual stored fields
|
|
52
|
+
$('#node-input-tag').val(tagName);
|
|
53
|
+
$('#node-input-tagId').val(tagId);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Initialize display (when editing existing node)
|
|
58
|
+
if (node.tagId && tagMap[node.tagId]) {
|
|
59
|
+
// Has tagId, construct tagSelected value
|
|
60
|
+
var tagName = node.tag || tagMap[node.tagId].name;
|
|
61
|
+
$('#node-input-tagSelected').val(tagName + '(' + node.tagId + ')');
|
|
62
|
+
} else if (node.tag && !node.tagId) {
|
|
63
|
+
// Old node: only has tag (tag.name), need to find corresponding tagId
|
|
64
|
+
// Note: if there are duplicate names, only the first match will be found
|
|
65
|
+
for (var tagId in tagMap) {
|
|
66
|
+
if (tagMap[tagId].name === node.tag) {
|
|
67
|
+
$('#node-input-tagSelected').val(node.tag + '(' + tagId + ')');
|
|
68
|
+
$('#node-input-tagId').val(tagId);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
24
73
|
});
|
|
25
74
|
}
|
|
26
75
|
});
|
|
@@ -32,10 +81,12 @@
|
|
|
32
81
|
<input type="text" id="node-input-name" placeholder="Name">
|
|
33
82
|
</div>
|
|
34
83
|
<div class="form-row">
|
|
35
|
-
<label for="node-input-
|
|
36
|
-
<input type="text" id="node-input-
|
|
84
|
+
<label for="node-input-tagSelected"><i class="fa fa-tag"></i> Tag</label>
|
|
85
|
+
<input type="text" id="node-input-tagSelected" list="fuxa-tags-daq-settings" placeholder="Select Tag">
|
|
37
86
|
<datalist id="fuxa-tags-daq-settings"></datalist>
|
|
38
87
|
</div>
|
|
88
|
+
<input type="hidden" id="node-input-tag">
|
|
89
|
+
<input type="hidden" id="node-input-tagId">
|
|
39
90
|
</script>
|
|
40
91
|
|
|
41
92
|
<script type="text/x-red" data-help-name="get-tag-daq-settings">
|
|
@@ -6,18 +6,22 @@ module.exports = function(RED) {
|
|
|
6
6
|
|
|
7
7
|
this.on('input', async function(msg) {
|
|
8
8
|
try {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} else {
|
|
17
|
-
node.error('Tag not found: ' + tagName, msg);
|
|
9
|
+
// Prefer config.tagId, fallback to config.tag or msg.tag for backward compatibility
|
|
10
|
+
var tagId = config.tagId;
|
|
11
|
+
if (!tagId) {
|
|
12
|
+
var tagName = config.tag || msg.tag;
|
|
13
|
+
if (tagName) {
|
|
14
|
+
// Backward compatibility: old nodes use tag.name, need to convert to tagId
|
|
15
|
+
tagId = fuxa.getTagId(tagName, null);
|
|
18
16
|
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (tagId) {
|
|
20
|
+
var settings = await fuxa.getTagDaqSettings(tagId);
|
|
21
|
+
msg.payload = settings;
|
|
22
|
+
node.send(msg);
|
|
19
23
|
} else {
|
|
20
|
-
node.error('Tag
|
|
24
|
+
node.error('Tag not found: ' + (config.tag || msg.tag || config.tagId), msg);
|
|
21
25
|
}
|
|
22
26
|
} catch (err) {
|
|
23
27
|
node.error(err, msg);
|
|
@@ -4,23 +4,72 @@
|
|
|
4
4
|
color: '#a6bbcf',
|
|
5
5
|
defaults: {
|
|
6
6
|
name: {value:""},
|
|
7
|
-
tag: {value:"",
|
|
7
|
+
tag: {value:""}, // Keep: tag name for display and backward compatibility
|
|
8
|
+
tagId: {value:""} // New: unique identifier (optional, for backward compatibility)
|
|
8
9
|
},
|
|
9
10
|
inputs:1,
|
|
10
11
|
outputs:1,
|
|
11
12
|
icon: "white-globe.png",
|
|
12
13
|
label: function() {
|
|
13
|
-
|
|
14
|
+
if (this.name) {
|
|
15
|
+
return this.name;
|
|
16
|
+
}
|
|
17
|
+
// Display tag name or tagId
|
|
18
|
+
return this.tag || this.tagId || "get tag";
|
|
14
19
|
},
|
|
15
20
|
oneditprepare: function() {
|
|
21
|
+
var node = this;
|
|
22
|
+
var tagMap = {}; // Use tag.id as key to avoid tag.name duplication issues
|
|
23
|
+
|
|
16
24
|
$.getJSON('/nodered/fuxa/devices', function(data) {
|
|
17
25
|
var datalist = $('#fuxa-tags');
|
|
18
26
|
datalist.empty();
|
|
27
|
+
|
|
19
28
|
data.forEach(function(device) {
|
|
20
29
|
device.tags.forEach(function(tag) {
|
|
21
|
-
|
|
30
|
+
var fullName = device.name + ' - ' + tag.name;
|
|
31
|
+
// datalist option value format: tag.name(tag.id)
|
|
32
|
+
var optionValue = tag.name + '(' + tag.id + ')';
|
|
33
|
+
datalist.append('<option value="' + optionValue + '">' + fullName + '</option>');
|
|
34
|
+
tagMap[tag.id] = {
|
|
35
|
+
name: tag.name,
|
|
36
|
+
deviceName: device.name,
|
|
37
|
+
fullName: fullName
|
|
38
|
+
};
|
|
22
39
|
});
|
|
23
40
|
});
|
|
41
|
+
|
|
42
|
+
// Listen for tagSelected input changes
|
|
43
|
+
$('#node-input-tagSelected').on('change', function() {
|
|
44
|
+
var selectedValue = $(this).val();
|
|
45
|
+
// Parse format: tag.name(tag.id)
|
|
46
|
+
var match = selectedValue.match(/^(.+)\(([^)]+)\)$/);
|
|
47
|
+
if (match) {
|
|
48
|
+
var tagName = match[1];
|
|
49
|
+
var tagId = match[2];
|
|
50
|
+
|
|
51
|
+
// Set the actual stored fields
|
|
52
|
+
$('#node-input-tag').val(tagName);
|
|
53
|
+
$('#node-input-tagId').val(tagId);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Initialize display (when editing existing node)
|
|
58
|
+
if (node.tagId && tagMap[node.tagId]) {
|
|
59
|
+
// Has tagId, construct tagSelected value
|
|
60
|
+
var tagName = node.tag || tagMap[node.tagId].name;
|
|
61
|
+
$('#node-input-tagSelected').val(tagName + '(' + node.tagId + ')');
|
|
62
|
+
} else if (node.tag && !node.tagId) {
|
|
63
|
+
// Old node: only has tag (tag.name), need to find corresponding tagId
|
|
64
|
+
// Note: if there are duplicate names, only the first match will be found
|
|
65
|
+
for (var tagId in tagMap) {
|
|
66
|
+
if (tagMap[tagId].name === node.tag) {
|
|
67
|
+
$('#node-input-tagSelected').val(node.tag + '(' + tagId + ')');
|
|
68
|
+
$('#node-input-tagId').val(tagId);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
24
73
|
});
|
|
25
74
|
}
|
|
26
75
|
});
|
|
@@ -32,10 +81,12 @@
|
|
|
32
81
|
<input type="text" id="node-input-name" placeholder="Name">
|
|
33
82
|
</div>
|
|
34
83
|
<div class="form-row">
|
|
35
|
-
<label for="node-input-
|
|
36
|
-
<input type="text" id="node-input-
|
|
84
|
+
<label for="node-input-tagSelected"><i class="fa fa-tag"></i> Tag</label>
|
|
85
|
+
<input type="text" id="node-input-tagSelected" list="fuxa-tags" placeholder="Select Tag">
|
|
37
86
|
<datalist id="fuxa-tags"></datalist>
|
|
38
87
|
</div>
|
|
88
|
+
<input type="hidden" id="node-input-tag">
|
|
89
|
+
<input type="hidden" id="node-input-tagId">
|
|
39
90
|
</script>
|
|
40
91
|
|
|
41
92
|
<script type="text/x-red" data-help-name="get-tag">
|
|
@@ -7,14 +7,20 @@ module.exports = function(RED) {
|
|
|
7
7
|
|
|
8
8
|
this.on('input', function(msg) {
|
|
9
9
|
try {
|
|
10
|
-
|
|
10
|
+
// Prefer config.tagId, fallback to config.tag for backward compatibility
|
|
11
|
+
var tagId = config.tagId;
|
|
12
|
+
if (!tagId && config.tag) {
|
|
13
|
+
// Backward compatibility: old nodes use tag.name, need to convert to tagId
|
|
14
|
+
tagId = fuxa.getTagId(config.tag, null);
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
if (tagId) {
|
|
12
18
|
var value = fuxa.getTag(tagId);
|
|
13
19
|
msg.payload = value;
|
|
14
20
|
msg.topic = config.tag; // Set topic to tag name for join operations
|
|
15
21
|
node.send(msg);
|
|
16
22
|
} else {
|
|
17
|
-
node.error('Tag not found: ' + config.tag, msg);
|
|
23
|
+
node.error('Tag not found: ' + (config.tag || config.tagId), msg);
|
|
18
24
|
}
|
|
19
25
|
} catch (err) {
|
|
20
26
|
node.error(err, msg);
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
color: '#a6bbcf',
|
|
5
5
|
defaults: {
|
|
6
6
|
name: {value:""},
|
|
7
|
-
tag: {value:"",
|
|
7
|
+
tag: {value:""}, // Keep: tag name for display and backward compatibility
|
|
8
|
+
tagId: {value:""}, // New: unique identifier (optional, for backward compatibility)
|
|
8
9
|
enabled: {value:true},
|
|
9
10
|
interval: {value:1000},
|
|
10
11
|
deadband: {value:0}
|
|
@@ -13,17 +14,65 @@
|
|
|
13
14
|
outputs:1,
|
|
14
15
|
icon: "white-globe.png",
|
|
15
16
|
label: function() {
|
|
16
|
-
|
|
17
|
+
if (this.name) {
|
|
18
|
+
return this.name;
|
|
19
|
+
}
|
|
20
|
+
// Display tag name or tagId
|
|
21
|
+
return this.tag || this.tagId || "set tag daq settings";
|
|
17
22
|
},
|
|
18
23
|
oneditprepare: function() {
|
|
24
|
+
var node = this;
|
|
25
|
+
var tagMap = {}; // Use tag.id as key to avoid tag.name duplication issues
|
|
26
|
+
|
|
19
27
|
$.getJSON('/nodered/fuxa/devices', function(data) {
|
|
20
28
|
var datalist = $('#fuxa-tags-set-daq-settings');
|
|
21
29
|
datalist.empty();
|
|
30
|
+
|
|
22
31
|
data.forEach(function(device) {
|
|
23
32
|
device.tags.forEach(function(tag) {
|
|
24
|
-
|
|
33
|
+
var fullName = device.name + ' - ' + tag.name;
|
|
34
|
+
// datalist option value format: tag.name(tag.id)
|
|
35
|
+
var optionValue = tag.name + '(' + tag.id + ')';
|
|
36
|
+
datalist.append('<option value="' + optionValue + '">' + fullName + '</option>');
|
|
37
|
+
tagMap[tag.id] = {
|
|
38
|
+
name: tag.name,
|
|
39
|
+
deviceName: device.name,
|
|
40
|
+
fullName: fullName
|
|
41
|
+
};
|
|
25
42
|
});
|
|
26
43
|
});
|
|
44
|
+
|
|
45
|
+
// Listen for tagSelected input changes
|
|
46
|
+
$('#node-input-tagSelected').on('change', function() {
|
|
47
|
+
var selectedValue = $(this).val();
|
|
48
|
+
// Parse format: tag.name(tag.id)
|
|
49
|
+
var match = selectedValue.match(/^(.+)\(([^)]+)\)$/);
|
|
50
|
+
if (match) {
|
|
51
|
+
var tagName = match[1];
|
|
52
|
+
var tagId = match[2];
|
|
53
|
+
|
|
54
|
+
// Set the actual stored fields
|
|
55
|
+
$('#node-input-tag').val(tagName);
|
|
56
|
+
$('#node-input-tagId').val(tagId);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Initialize display (when editing existing node)
|
|
61
|
+
if (node.tagId && tagMap[node.tagId]) {
|
|
62
|
+
// Has tagId, construct tagSelected value
|
|
63
|
+
var tagName = node.tag || tagMap[node.tagId].name;
|
|
64
|
+
$('#node-input-tagSelected').val(tagName + '(' + node.tagId + ')');
|
|
65
|
+
} else if (node.tag && !node.tagId) {
|
|
66
|
+
// Old node: only has tag (tag.name), need to find corresponding tagId
|
|
67
|
+
// Note: if there are duplicate names, only the first match will be found
|
|
68
|
+
for (var tagId in tagMap) {
|
|
69
|
+
if (tagMap[tagId].name === node.tag) {
|
|
70
|
+
$('#node-input-tagSelected').val(node.tag + '(' + tagId + ')');
|
|
71
|
+
$('#node-input-tagId').val(tagId);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
27
76
|
});
|
|
28
77
|
}
|
|
29
78
|
});
|
|
@@ -35,10 +84,12 @@
|
|
|
35
84
|
<input type="text" id="node-input-name" placeholder="Name">
|
|
36
85
|
</div>
|
|
37
86
|
<div class="form-row">
|
|
38
|
-
<label for="node-input-
|
|
39
|
-
<input type="text" id="node-input-
|
|
87
|
+
<label for="node-input-tagSelected"><i class="fa fa-tag"></i> Tag</label>
|
|
88
|
+
<input type="text" id="node-input-tagSelected" list="fuxa-tags-set-daq-settings" placeholder="Select Tag">
|
|
40
89
|
<datalist id="fuxa-tags-set-daq-settings"></datalist>
|
|
41
90
|
</div>
|
|
91
|
+
<input type="hidden" id="node-input-tag">
|
|
92
|
+
<input type="hidden" id="node-input-tagId">
|
|
42
93
|
<div class="form-row">
|
|
43
94
|
<label for="node-input-enabled"> </label>
|
|
44
95
|
<input type="checkbox" id="node-input-enabled" style="display:inline-block; width:15px; vertical-align:baseline;">
|
|
@@ -6,29 +6,33 @@ module.exports = function(RED) {
|
|
|
6
6
|
|
|
7
7
|
this.on('input', async function(msg) {
|
|
8
8
|
try {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
// Prefer config.tagId, fallback to config.tag or msg.tag for backward compatibility
|
|
10
|
+
var tagId = config.tagId;
|
|
11
|
+
if (!tagId) {
|
|
12
|
+
var tagName = config.tag || msg.tag;
|
|
13
|
+
if (tagName) {
|
|
14
|
+
// Backward compatibility: old nodes use tag.name, need to convert to tagId
|
|
15
|
+
tagId = fuxa.getTagId(tagName, null);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (tagId) {
|
|
20
|
+
var settings = {
|
|
21
|
+
enabled: config.enabled,
|
|
22
|
+
interval: config.interval,
|
|
23
|
+
deadband: config.deadband
|
|
24
|
+
};
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
// Override with message properties if provided
|
|
27
|
+
if (msg.enabled !== undefined) settings.enabled = msg.enabled;
|
|
28
|
+
if (msg.interval !== undefined) settings.interval = msg.interval;
|
|
29
|
+
if (msg.deadband !== undefined) settings.deadband = msg.deadband;
|
|
23
30
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
} else {
|
|
28
|
-
node.error('Tag not found: ' + tagName, msg);
|
|
29
|
-
}
|
|
31
|
+
var result = await fuxa.setTagDaqSettings(tagId, settings);
|
|
32
|
+
msg.payload = result;
|
|
33
|
+
node.send(msg);
|
|
30
34
|
} else {
|
|
31
|
-
node.error('Tag
|
|
35
|
+
node.error('Tag not found: ' + (config.tag || msg.tag || config.tagId), msg);
|
|
32
36
|
}
|
|
33
37
|
} catch (err) {
|
|
34
38
|
node.error(err, msg);
|