Compare commits

...

19 Commits

Author SHA1 Message Date
znetsixe
ea33b3bba3 fix: add missing closing brace in emergencystop case block
The emergencystop case was missing its closing } before the
simulateMeasurement case, causing a SyntaxError on load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 08:44:49 +02:00
znetsixe
f363ee53ef Merge commit '4cf46f3' into HEAD
# Conflicts:
#	src/nodeClass.js
#	src/specificClass.js
2026-03-31 18:23:38 +02:00
Rene De Ren
4cf46f33c9 Expose output format selectors in editor 2026-03-12 16:39:25 +01:00
Rene De Ren
7b9fdd7342 fix: correct logging config path and child registration ID
Fixed eneableLog typo accessing wrong config path — now uses
machineConfig.general.logging.enabled/logLevel. Changed _registerChild
to use this.node.id consistent with all other nodes. Removed debug console.log.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:33:28 +01:00
Rene De Ren
bb986c2dc8 refactor: adopt POSITIONS constants and fix ESLint warnings
Replace hardcoded position strings with POSITIONS.* constants.
Prefix unused variables with _ to resolve no-unused-vars warnings.
Fix no-prototype-builtins where applicable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 15:35:28 +01:00
Rene De Ren
46dd2ca37a Migrate _loadConfig to use ConfigManager.buildConfig()
Replaces manual base config construction with shared buildConfig() method.
Node now only specifies domain-specific config sections.

Part of #1: Extract base config schema

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 14:59:35 +01:00
Rene De Ren
ccfa90394b Fix ESLint errors and bugs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 13:39:57 +01:00
znetsixe
e236cccfd6 Merge branch 'dev-Rene' 2025-12-19 10:23:25 +01:00
p.vanderwilt
99b45c87e4 Rename _updateSourceSink to updateSourceSink for outside access 2025-11-14 12:55:11 +01:00
p.vanderwilt
0a98b12224 Merge pull request 'Implement reactor recirculation' (#4) from dev-Pieter into main
Reviewed-on: https://gitea.centraal.wbd-rd.nl/RnD/rotatingMachine/pulls/4
2025-11-06 13:58:25 +00:00
p.vanderwilt
b6d268659a Refactor flow handling: rename reactor references to source and sink and fix config minor bug 2025-11-06 14:50:40 +01:00
p.vanderwilt
303dfc477d Add flow number configuration and UI input for rotating machine 2025-10-31 14:16:00 +01:00
p.vanderwilt
ac40a93ef1 Simplify child registration error handling 2025-10-31 13:07:52 +01:00
p.vanderwilt
a8fb56bfb8 Add upstream and downstream reactor handling; improve error logging 2025-10-22 14:41:35 +02:00
HorriblePerson555
d7cc6a4a8b Enhance child registration logging and add validation for measurement child 2025-10-17 13:38:05 +02:00
HorriblePerson555
37e6523c55 Refactor child registration to use dedicated connection methods for measurement and reactor types 2025-10-16 16:32:20 +02:00
5a14f44fdd Merge pull request 'dev-Rene' (#2) from dev-Rene into main
Reviewed-on: https://gitea.centraal.wbd-rd.nl/RnD/rotatingMachine/pulls/2
2025-10-16 13:21:38 +00:00
p.vanderwilt
c081acae4e Remove non-implemented temperature handling function 2025-10-10 13:27:31 +02:00
08185243bc Merge pull request 'dev-Rene' (#1) from dev-Rene into main
Reviewed-on: https://gitea.centraal.wbd-rd.nl/RnD/rotatingMachine/pulls/1
2025-10-06 14:16:18 +00:00
3 changed files with 49 additions and 33 deletions

View File

@@ -26,6 +26,8 @@
cooldown: { value: 0 }, cooldown: { value: 0 },
movementMode : { value: "staticspeed" }, // static or dynamic movementMode : { value: "staticspeed" }, // static or dynamic
machineCurve : { value: {}}, machineCurve : { value: {}},
processOutputFormat: { value: "process" },
dbaseOutputFormat: { value: "influxdb" },
//define asset properties //define asset properties
uuid: { value: "" }, uuid: { value: "" },
@@ -148,6 +150,24 @@
</select> </select>
</div> </div>
<h3>Output Formats</h3>
<div class="form-row">
<label for="node-input-processOutputFormat"><i class="fa fa-random"></i> Process Output</label>
<select id="node-input-processOutputFormat" style="width:60%;">
<option value="process">process</option>
<option value="json">json</option>
<option value="csv">csv</option>
</select>
</div>
<div class="form-row">
<label for="node-input-dbaseOutputFormat"><i class="fa fa-database"></i> Database Output</label>
<select id="node-input-dbaseOutputFormat" style="width:60%;">
<option value="influxdb">influxdb</option>
<option value="json">json</option>
<option value="csv">csv</option>
</select>
</div>
<!-- Asset fields injected here --> <!-- Asset fields injected here -->
<div id="asset-fields-placeholder"></div> <div id="asset-fields-placeholder"></div>

View File

@@ -42,6 +42,7 @@ class nodeClass {
* @param {object} uiConfig - Raw config from Node-RED UI. * @param {object} uiConfig - Raw config from Node-RED UI.
*/ */
_loadConfig(uiConfig,node) { _loadConfig(uiConfig,node) {
const cfgMgr = new configManager();
const resolvedAssetUuid = uiConfig.assetUuid || uiConfig.uuid || null; const resolvedAssetUuid = uiConfig.assetUuid || uiConfig.uuid || null;
const resolvedAssetTagCode = uiConfig.assetTagCode || uiConfig.assetTagNumber || null; const resolvedAssetTagCode = uiConfig.assetTagCode || uiConfig.assetTagNumber || null;
const flowUnit = this._resolveUnitOrFallback(uiConfig.unit, 'volumeFlowRate', 'm3/h', 'flow'); const flowUnit = this._resolveUnitOrFallback(uiConfig.unit, 'volumeFlowRate', 'm3/h', 'flow');
@@ -52,33 +53,24 @@ class nodeClass {
control: this._resolveControlUnitOrFallback(uiConfig.curveControlUnit, '%'), control: this._resolveControlUnitOrFallback(uiConfig.curveControlUnit, '%'),
}; };
// Merge UI config over defaults // Build config: base sections + rotatingMachine-specific domain config
this.config = { this.config = cfgMgr.buildConfig(this.name, uiConfig, node.id, {
general: { flowNumber: uiConfig.flowNumber
name: this.name, });
id: node.id, // node.id is for the child registration process
unit: flowUnit, // Override asset with rotatingMachine-specific fields
logging: { this.config.asset = {
enabled: uiConfig.enableLog, ...this.config.asset,
logLevel: uiConfig.logLevel uuid: resolvedAssetUuid,
} tagCode: resolvedAssetTagCode,
}, tagNumber: uiConfig.assetTagNumber || null,
asset: { unit: flowUnit,
uuid: resolvedAssetUuid, // support both legacy and current editor field names curveUnits
tagCode: resolvedAssetTagCode, // support both legacy and current editor field names
tagNumber: uiConfig.assetTagNumber || null,
supplier: uiConfig.supplier,
category: uiConfig.category, //add later to define as the software type
type: uiConfig.assetType,
model: uiConfig.model,
unit: flowUnit,
curveUnits
},
functionality: {
positionVsParent: uiConfig.positionVsParent
}
}; };
// Ensure general unit uses resolved flow unit
this.config.general.unit = flowUnit;
// Utility for formatting outputs // Utility for formatting outputs
this._output = new outputUtils(); this._output = new outputUtils();
} }
@@ -253,7 +245,7 @@ class nodeClass {
this.node.send([ this.node.send([
null, null,
null, null,
{ topic: 'registerChild', payload: this.config.general.id, positionVsParent: this.config?.functionality?.positionVsParent || 'atEquipment' }, { topic: 'registerChild', payload: this.node.id, positionVsParent: this.config?.functionality?.positionVsParent || 'atEquipment' },
]); ]);
}, 100); }, 100);
} }
@@ -299,7 +291,7 @@ class nodeClass {
try { try {
switch(msg.topic) { switch(msg.topic) {
case 'registerChild': case 'registerChild': {
// Register this node as a child of the parent node // Register this node as a child of the parent node
const childId = msg.payload; const childId = msg.payload;
const childObj = this.RED.nodes.getNode(childId); const childObj = this.RED.nodes.getNode(childId);
@@ -309,26 +301,30 @@ class nodeClass {
} }
m.childRegistrationUtils.registerChild(childObj.source ,msg.positionVsParent); m.childRegistrationUtils.registerChild(childObj.source ,msg.positionVsParent);
break; break;
}
case 'setMode': case 'setMode':
m.setMode(msg.payload); m.setMode(msg.payload);
break; break;
case 'execSequence': case 'execSequence': {
const { source, action, parameter } = msg.payload; const { source, action, parameter } = msg.payload;
m.handleInput(source, action, parameter); m.handleInput(source, action, parameter);
break; break;
case 'execMovement': }
case 'execMovement': {
const { source: mvSource, action: mvAction, setpoint } = msg.payload; const { source: mvSource, action: mvAction, setpoint } = msg.payload;
m.handleInput(mvSource, mvAction, Number(setpoint)); m.handleInput(mvSource, mvAction, Number(setpoint));
break; break;
case 'flowMovement': }
case 'flowMovement': {
const { source: fmSource, action: fmAction, setpoint: fmSetpoint } = msg.payload; const { source: fmSource, action: fmAction, setpoint: fmSetpoint } = msg.payload;
m.handleInput(fmSource, fmAction, Number(fmSetpoint)); m.handleInput(fmSource, fmAction, Number(fmSetpoint));
break; break;
case 'emergencystop': }
case 'emergencystop': {
const { source: esSource, action: esAction } = msg.payload; const { source: esSource, action: esAction } = msg.payload;
m.handleInput(esSource, esAction); m.handleInput(esSource, esAction);
break; break;
}
case 'simulateMeasurement': case 'simulateMeasurement':
{ {
const payload = msg.payload || {}; const payload = msg.payload || {};

View File

@@ -1,5 +1,5 @@
const EventEmitter = require('events'); const EventEmitter = require('events');
const {loadCurve,gravity,logger,configUtils,configManager,state, nrmse, MeasurementContainer, predict, interpolation , childRegistrationUtils,coolprop, convert} = require('generalFunctions'); const {loadCurve,gravity,logger,configUtils,configManager,state, nrmse, MeasurementContainer, predict, interpolation , childRegistrationUtils,coolprop, convert, POSITIONS} = require('generalFunctions');
const CANONICAL_UNITS = Object.freeze({ const CANONICAL_UNITS = Object.freeze({
pressure: 'Pa', pressure: 'Pa',