@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,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 || "set 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-set');
|
|
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-set" placeholder="Select Tag">
|
|
37
86
|
<datalist id="fuxa-tags-set"></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="set-tag">
|
|
@@ -7,12 +7,18 @@ module.exports = function(RED) {
|
|
|
7
7
|
|
|
8
8
|
this.on('input', async 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
|
await fuxa.setTag(tagId, msg.payload);
|
|
13
19
|
node.send(msg);
|
|
14
20
|
} else {
|
|
15
|
-
node.error('Tag not found: ' + config.tag, msg);
|
|
21
|
+
node.error('Tag not found: ' + (config.tag || config.tagId), msg);
|
|
16
22
|
}
|
|
17
23
|
} catch (err) {
|
|
18
24
|
node.error(err, msg);
|
package/main.js
CHANGED
|
@@ -148,6 +148,12 @@ try {
|
|
|
148
148
|
if (mysettings.tokenExpiresIn) {
|
|
149
149
|
settings.tokenExpiresIn = mysettings.tokenExpiresIn;
|
|
150
150
|
}
|
|
151
|
+
if (!utils.isNullOrUndefined(mysettings.enableRefreshCookieAuth)) {
|
|
152
|
+
settings.enableRefreshCookieAuth = mysettings.enableRefreshCookieAuth;
|
|
153
|
+
}
|
|
154
|
+
if (mysettings.refreshTokenExpiresIn) {
|
|
155
|
+
settings.refreshTokenExpiresIn = mysettings.refreshTokenExpiresIn;
|
|
156
|
+
}
|
|
151
157
|
if (mysettings.secretCode) {
|
|
152
158
|
settings.secretCode = mysettings.secretCode;
|
|
153
159
|
}
|
|
@@ -189,6 +195,12 @@ try {
|
|
|
189
195
|
logger.error('Error loading user settings file: ' + userSettingsFile)
|
|
190
196
|
}
|
|
191
197
|
|
|
198
|
+
// Ensure secure mode never runs with an empty/static-known JWT secret.
|
|
199
|
+
if (settings.secureEnabled && !settings.secretCode) {
|
|
200
|
+
settings.secretCode = utils.generateSecretCode();
|
|
201
|
+
logger.warn('Generated a random JWT secret in memory because secureEnabled=true and secretCode was missing. Persist it in settings for stable sessions across restarts.');
|
|
202
|
+
}
|
|
203
|
+
|
|
192
204
|
// Check logger
|
|
193
205
|
if (!settings.logDir) {
|
|
194
206
|
settings.logDir = path.resolve(rootDir, '_logs');
|
|
@@ -260,6 +272,7 @@ var www = path.resolve(__dirname, '../client/dist');
|
|
|
260
272
|
if (!fs.existsSync(www)) { // compatibility with docker/npm/electron
|
|
261
273
|
www = path.resolve(__dirname, './dist');
|
|
262
274
|
}
|
|
275
|
+
|
|
263
276
|
settings.httpStatic = settings.httpStatic || www;
|
|
264
277
|
|
|
265
278
|
if (parsedArgs.port !== undefined) {
|
|
@@ -321,10 +334,13 @@ const allowCrossDomain = function (req, res, next) {
|
|
|
321
334
|
|
|
322
335
|
if (isOriginAllowed(origin)) {
|
|
323
336
|
res.header('Access-Control-Allow-Origin', origin || '*');
|
|
337
|
+
if (settings.enableRefreshCookieAuth) {
|
|
338
|
+
res.header('Access-Control-Allow-Credentials', 'true');
|
|
339
|
+
}
|
|
324
340
|
}
|
|
325
341
|
|
|
326
342
|
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
|
|
327
|
-
res.header('Access-Control-Allow-Headers', 'x-access-token, x-auth-user, Origin, Content-Type, Accept');
|
|
343
|
+
res.header('Access-Control-Allow-Headers', 'x-access-token, x-auth-user, Origin, Content-Type, Accept, Skip-Auth, Skip-Error');
|
|
328
344
|
|
|
329
345
|
|
|
330
346
|
if (req.method === 'OPTIONS') {
|
|
@@ -348,22 +364,24 @@ app.use('/_widgets', express.static(settings.widgetsFileDir));
|
|
|
348
364
|
app.use('/snapshots', express.static(settings.webcamSnapShotsDir))
|
|
349
365
|
|
|
350
366
|
var accessLogStream = fs.createWriteStream(settings.logDir + '/api.log', { flags: 'a' });
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
}
|
|
367
|
+
if (runtime.settings.logApiLevel !== 'none') {
|
|
368
|
+
app.use(morgan('combined', {
|
|
369
|
+
stream: accessLogStream,
|
|
370
|
+
skip: function (req, res) { return res.statusCode < 400 }
|
|
371
|
+
}));
|
|
372
|
+
|
|
373
|
+
app.use(morgan('dev', {
|
|
374
|
+
skip: function (req, res) {
|
|
375
|
+
return res.statusCode < 400
|
|
376
|
+
}, stream: process.stderr
|
|
377
|
+
}));
|
|
378
|
+
|
|
379
|
+
app.use(morgan('dev', {
|
|
380
|
+
skip: function (req, res) {
|
|
381
|
+
return res.statusCode >= 400
|
|
382
|
+
}, stream: process.stdout
|
|
383
|
+
}));
|
|
384
|
+
}
|
|
367
385
|
|
|
368
386
|
function mountSwaggerIfEnabled() {
|
|
369
387
|
const swaggerEnabled = settings.swagger || settings.swaggerEnabled;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frangoteam/fuxa-min",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Web-based Process Visualization (SCADA/HMI/Dashboard) software",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"scripts": {
|
|
@@ -36,12 +36,13 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@influxdata/influxdb-client": "1.25.0",
|
|
39
|
+
"@questdb/nodejs-client": "3.0.0",
|
|
39
40
|
"@tdengine/rest": "3.0.2",
|
|
40
41
|
"ads-client": "2.1.0",
|
|
41
42
|
"app-root-path": "2.2.1",
|
|
42
43
|
"async": "3.2.3",
|
|
43
44
|
"async-mutex": "0.5.0",
|
|
44
|
-
"axios": "
|
|
45
|
+
"axios": "1.13.5",
|
|
45
46
|
"bcryptjs": "2.4.3",
|
|
46
47
|
"bluebird": "3.7.2",
|
|
47
48
|
"body-parser": "1.20.3",
|
|
@@ -52,19 +53,20 @@
|
|
|
52
53
|
"fontkit": "^2.0.2",
|
|
53
54
|
"fs-extra": "7.0.1",
|
|
54
55
|
"influx": "5.9.3",
|
|
55
|
-
"ip": "2.0.1",
|
|
56
|
+
"ip": "~2.0.1",
|
|
56
57
|
"jsonwebtoken": "9.0.0",
|
|
57
58
|
"live-plugin-manager": "0.15.1",
|
|
58
59
|
"modbus-serial": "8.0.19",
|
|
59
|
-
"morgan": "1.10.
|
|
60
|
+
"morgan": "1.10.1",
|
|
60
61
|
"mqtt": "4.3.7",
|
|
61
62
|
"node-bacnet": "0.2.4",
|
|
62
63
|
"node-opcua": "2.149.0",
|
|
63
64
|
"node-red": "^4.1.0",
|
|
64
65
|
"node-schedule": "2.1.1",
|
|
65
|
-
"nodemailer": "7.0.
|
|
66
|
+
"nodemailer": "7.0.13",
|
|
66
67
|
"nopt": "5.0.0",
|
|
67
68
|
"pdfmake": "0.2.5",
|
|
69
|
+
"pg": "8.18.0",
|
|
68
70
|
"socket.io": "4.8.1",
|
|
69
71
|
"sqlite3": "5.1.5",
|
|
70
72
|
"swagger-ui-express": "^5.0.1",
|
|
@@ -72,6 +74,9 @@
|
|
|
72
74
|
"ws": "8.18.0",
|
|
73
75
|
"yamljs": "^0.3.0"
|
|
74
76
|
},
|
|
77
|
+
"overrides": {
|
|
78
|
+
"tar": "^7.4.3"
|
|
79
|
+
},
|
|
75
80
|
"devDependencies": {
|
|
76
81
|
"@mapbox/node-pre-gyp": "^1.0.0",
|
|
77
82
|
"@types/express": "5.0.0",
|
|
@@ -24,7 +24,7 @@ function ODBCclient(_data, _logger, _events) {
|
|
|
24
24
|
* initialize the device type
|
|
25
25
|
*/
|
|
26
26
|
this.init = function (_type) {
|
|
27
|
-
console.error('Not supported!');
|
|
27
|
+
console.error('Not supported! (odbc.init)');
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/**
|
|
@@ -165,14 +165,14 @@ function ODBCclient(_data, _logger, _events) {
|
|
|
165
165
|
* Return Tags values array { id: <name>, value: <value> }
|
|
166
166
|
*/
|
|
167
167
|
this.getValues = function () {
|
|
168
|
-
console.error('Not supported!');
|
|
168
|
+
console.error('Not supported! (odbc.getValues)');
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
/**
|
|
172
172
|
* Return Tag value { id: <name>, value: <value>, ts: <lastTimestampValue> }
|
|
173
173
|
*/
|
|
174
174
|
this.getValue = function (tagid) {
|
|
175
|
-
console.error(
|
|
175
|
+
console.error(`Not supported! (odbc.getValue) (TagID: ${tagid})`);
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
/**
|
|
@@ -186,14 +186,14 @@ function ODBCclient(_data, _logger, _events) {
|
|
|
186
186
|
* Return Tag property to show in frontend
|
|
187
187
|
*/
|
|
188
188
|
this.getTagProperty = function (tagid) {
|
|
189
|
-
console.error(
|
|
189
|
+
console.error(`Not supported! (odbc.getTagProperty) (TagID: ${tagid})`);
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
/**
|
|
193
193
|
* Set the Tag value to device
|
|
194
194
|
*/
|
|
195
195
|
this.setValue = function (tagid, value) {
|
|
196
|
-
console.error(
|
|
196
|
+
console.error(`Not supported! (odbc.setValue) (TagID: ${tagid}, Value: ${value})`);
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
/**
|
|
@@ -14,7 +14,7 @@ function DeviceTemplate(_data, _logger, _events) {
|
|
|
14
14
|
* initialize the device type
|
|
15
15
|
*/
|
|
16
16
|
this.init = function (_type) {
|
|
17
|
-
console.error('Not supported!');
|
|
17
|
+
console.error('Not supported! (template.init)');
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -22,7 +22,7 @@ function DeviceTemplate(_data, _logger, _events) {
|
|
|
22
22
|
* Emit connection status to clients, clear all Tags values
|
|
23
23
|
*/
|
|
24
24
|
this.connect = function () {
|
|
25
|
-
console.error('Not supported!');
|
|
25
|
+
console.error('Not supported! (template.connect)');
|
|
26
26
|
// events.emit('device-status:changed', { id: data.id, status: 'connect-ok' });
|
|
27
27
|
// events.emit('device-status:changed', { id: data.id, status: 'connect-error' });
|
|
28
28
|
}
|
|
@@ -33,7 +33,7 @@ function DeviceTemplate(_data, _logger, _events) {
|
|
|
33
33
|
* Emit connection status to clients, clear all Tags values
|
|
34
34
|
*/
|
|
35
35
|
this.disconnect = function () {
|
|
36
|
-
console.error('Not supported!');
|
|
36
|
+
console.error('Not supported! (template.disconnect)');
|
|
37
37
|
// events.emit('device-status:changed', { id: data.id, status: 'connect-off' });
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -42,7 +42,7 @@ function DeviceTemplate(_data, _logger, _events) {
|
|
|
42
42
|
* Update the tags values list, save in DAQ if value changed or in interval and emit values to clients
|
|
43
43
|
*/
|
|
44
44
|
this.polling = async function () {
|
|
45
|
-
console.error('Not supported!');
|
|
45
|
+
console.error('Not supported! (template.polling)');
|
|
46
46
|
// events.emit('device-value:changed', { id: data.name, values: values });
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -50,49 +50,49 @@ function DeviceTemplate(_data, _logger, _events) {
|
|
|
50
50
|
* Load Tags attribute to read with polling
|
|
51
51
|
*/
|
|
52
52
|
this.load = function (_data) {
|
|
53
|
-
console.error(
|
|
53
|
+
console.error(`Not supported! (template.load) (Data: ${_data})`);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
57
|
* Return Tags values array { id: <name>, value: <value> }
|
|
58
58
|
*/
|
|
59
59
|
this.getValues = function () {
|
|
60
|
-
console.error('Not supported!');
|
|
60
|
+
console.error('Not supported! (template.getValues)');
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
64
|
* Return Tag value { id: <name>, value: <value>, ts: <lastTimestampValue> }
|
|
65
65
|
*/
|
|
66
66
|
this.getValue = function (tagid) {
|
|
67
|
-
console.error(
|
|
67
|
+
console.error(`Not supported! (template.getValue) (TagID: ${tagid})`);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
71
|
* Return connection status 'connect-off', 'connect-ok', 'connect-error', 'connect-busy'
|
|
72
72
|
*/
|
|
73
73
|
this.getStatus = function () {
|
|
74
|
-
console.error('Not supported!');
|
|
74
|
+
console.error('Not supported! (template.getStatus)');
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
78
|
* Return Tag property to show in frontend
|
|
79
79
|
*/
|
|
80
80
|
this.getTagProperty = function (tagid) {
|
|
81
|
-
console.error(
|
|
81
|
+
console.error(`Not supported! (template.getTagProperty) (TagID: ${tagid})`);
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
85
|
* Set the Tag value to device
|
|
86
86
|
*/
|
|
87
87
|
this.setValue = function (tagid, value) {
|
|
88
|
-
console.error(
|
|
88
|
+
console.error(`Not supported! (template.setValue) (TagID: ${tagid}, Value: ${value})`);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
92
|
* Return if device is connected
|
|
93
93
|
*/
|
|
94
94
|
this.isConnected = function () {
|
|
95
|
-
console.error('Not supported!');
|
|
95
|
+
console.error('Not supported! (template.isConnected)');
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**
|
|
@@ -107,7 +107,7 @@ function DeviceTemplate(_data, _logger, _events) {
|
|
|
107
107
|
* @returns
|
|
108
108
|
*/
|
|
109
109
|
this.lastReadTimestamp = () => {
|
|
110
|
-
console.error('Not supported!');
|
|
110
|
+
console.error('Not supported! (template.lastReadTimestamp)');
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
/**
|
|
@@ -115,7 +115,7 @@ function DeviceTemplate(_data, _logger, _events) {
|
|
|
115
115
|
* @returns
|
|
116
116
|
*/
|
|
117
117
|
this.getTagDaqSettings = (tagId) => {
|
|
118
|
-
console.error(
|
|
118
|
+
console.error(`Not supported! (template.getTagDaqSettings) (TagID: ${tagId})`);
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
/**
|
|
@@ -123,7 +123,7 @@ function DeviceTemplate(_data, _logger, _events) {
|
|
|
123
123
|
* @returns
|
|
124
124
|
*/
|
|
125
125
|
this.setTagDaqSettings = (tagId, settings) => {
|
|
126
|
-
console.error(
|
|
126
|
+
console.error(`Not supported! (template.setTagDaqSettings) (TagID: ${tagId}, Settings: ${settings})`);
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
@@ -21,6 +21,7 @@ var logger;
|
|
|
21
21
|
var daqDB = {}; // list of daqDB node: SQlite one pro device, influxDB only one
|
|
22
22
|
var currentStorateDB;
|
|
23
23
|
var runtime;
|
|
24
|
+
var questDbModule = null;
|
|
24
25
|
|
|
25
26
|
function init(_settings, _log, _runtime) {
|
|
26
27
|
settings = _settings;
|
|
@@ -42,7 +43,7 @@ function reset() {
|
|
|
42
43
|
function addDaqNode(_id, fncgetprop) {
|
|
43
44
|
var id = _id;
|
|
44
45
|
const dbType = _getDbType();
|
|
45
|
-
if (dbType === DaqStoreTypeEnum.influxDB || dbType === DaqStoreTypeEnum.influxDB18 || dbType === DaqStoreTypeEnum.TDengine) {
|
|
46
|
+
if (dbType === DaqStoreTypeEnum.influxDB || dbType === DaqStoreTypeEnum.influxDB18 || dbType === DaqStoreTypeEnum.TDengine || dbType === DaqStoreTypeEnum.questDB) {
|
|
46
47
|
id = dbType;
|
|
47
48
|
}
|
|
48
49
|
if (!daqDB[id]) {
|
|
@@ -50,6 +51,14 @@ function addDaqNode(_id, fncgetprop) {
|
|
|
50
51
|
daqDB[id] = InfluxDB.create(settings, logger, currentStorateDB);
|
|
51
52
|
} else if(id === DaqStoreTypeEnum.TDengine){
|
|
52
53
|
daqDB[id] = TDengine.create(settings, logger, currentStorateDB);
|
|
54
|
+
} else if(id === DaqStoreTypeEnum.questDB){
|
|
55
|
+
const QuestDB = _getQuestDbModule();
|
|
56
|
+
if (QuestDB) {
|
|
57
|
+
daqDB[id] = QuestDB.create(settings, logger, currentStorateDB);
|
|
58
|
+
} else {
|
|
59
|
+
logger.warn('daqstorage: QuestDB storage selected but package dependencies are not installed. Falling back to SQLite.');
|
|
60
|
+
daqDB[id] = SqliteDB.create(settings, logger, id, currentStorateDB);
|
|
61
|
+
}
|
|
53
62
|
} else {
|
|
54
63
|
daqDB[id] = SqliteDB.create(settings, logger, id, currentStorateDB);
|
|
55
64
|
}
|
|
@@ -160,16 +169,33 @@ function _getDaqNode(tagid) {
|
|
|
160
169
|
|
|
161
170
|
function _getDbType() {
|
|
162
171
|
if (settings.daqstore && settings.daqstore.type) {
|
|
172
|
+
if (settings.daqstore.type === 'QuestDB') {
|
|
173
|
+
return DaqStoreTypeEnum.questDB;
|
|
174
|
+
}
|
|
163
175
|
return settings.daqstore.type;
|
|
164
176
|
}
|
|
165
177
|
return DaqStoreTypeEnum.SQlite;
|
|
166
178
|
}
|
|
167
179
|
|
|
180
|
+
function _getQuestDbModule() {
|
|
181
|
+
if (questDbModule) {
|
|
182
|
+
return questDbModule;
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
questDbModule = require("./questdb");
|
|
186
|
+
} catch (err) {
|
|
187
|
+
questDbModule = null;
|
|
188
|
+
logger.warn(`daqstorage: QuestDB module unavailable (${err.message})`);
|
|
189
|
+
}
|
|
190
|
+
return questDbModule;
|
|
191
|
+
}
|
|
192
|
+
|
|
168
193
|
var DaqStoreTypeEnum = {
|
|
169
194
|
SQlite: 'SQlite',
|
|
170
195
|
influxDB: 'influxDB',
|
|
171
196
|
influxDB18: 'influxDB18',
|
|
172
197
|
TDengine: 'TDengine',
|
|
198
|
+
questDB: 'questDB',
|
|
173
199
|
}
|
|
174
200
|
|
|
175
201
|
function _getValue(value) {
|
|
@@ -187,4 +213,4 @@ module.exports = {
|
|
|
187
213
|
getNodesValues: getNodesValues,
|
|
188
214
|
checkRetention: checkRetention,
|
|
189
215
|
getCurrentStorageFnc: getCurrentStorageFnc,
|
|
190
|
-
};
|
|
216
|
+
};
|